js中的数据类型转换及变量提升

数据类型转换

// --------数据类型转换的4大核心标准--------
/* 
 * 把其他数据类型转为 Number 类型
      1、需要特定转化为 Number 的
        + Number(val)
        + parseInt/parseFloat(val)
      2、隐式转换(浏览器内部默认要先转为 Number 再进行计算的)
        + isNaN(val)
        + 数学运算(特殊情况:+在出现字符串的情况下不是数学运算,而是字符串拼接)
        + 在 == 比较的时候,有些值需要转为数字再进行比较
        + ...
      ...
  
  * 把其他数据类型转为 String
      1、能使用的方法
        + toString()
        + String(val)
      2、隐式转化(一般是调用其toString方法)
        + 加号运算的时候,如果某一遍出现字符串,则是字符串拼接
        + 吧对象转为数字,需要先调用其toString()犯法转为字符串,再去转换为数字
        + 基于alert/confirm/prompt/document.write...这些方式输出内容,都是把内容先转化为字符串,然后再输出的
        + ...
      ......

  * 把其他类型转为 Boolean
      1、基于以下方式可以把其他类型转为 Boolean
        + !  转换为布尔值后取反
        + !!  转换为布尔类型
      2、隐式转换
        + 在循环或者条件判断中,条件处理的结果就是布尔类型值
        + ...
  
    规则:只有 0、NaN、null、undefined、空字符串 这五个值变为布尔值为 false,其余的都是true

  * 在 == 比较的过程中,数据的转化规则:
     【类型一样的几个特殊点】:
          {} == {} :false 对象比较的是堆内存的地址
          [] == [] :false
          NaN == NaN :false NaN跟任何值都不相等,包括它自己
     【类型不一样的转换规则】:
          1、null == undefined:true,但是换成===结果是false(因为类型不一样),剩下null/undefined和其他任何数据类型值都不相等
          2、字符串 == 对象  要把对象转为字符串
          3、剩下如果==两边数据类型不一致,都是需要转换为数字再进行比较
*/


 console.log([] == false); // true  
// 对象 == 布尔  两边类型不一致,都转为数字(隐式转换)
// 对象转换为数字:先toString转为字符串(应该是先基于valueOf获得原始值,没有原始值再去toString),再转为数字的
// 左边: [] -> '' -> 0
// 右边:false -> 0
// => true
console.log(![] == false); // true  
// ![] 已经是布尔值类型了,所以这个==的两边类型是一样的,
// 左边:把[]转为布尔值再取反,为false,
// false == false
// => true



// 把其他类型转换为字符串,一般都是直接用""包起来,只有{}普通对象调取toString是调取Object.prototype.toString,不是转为字符串,而是检测数据类型,返回结果是 "[object object]"


// 把其他类型转换为数字   Number机制
 console.log(Number(''));  // 0
console.log(Number('10')); // 10
console.log(Number('10px'));  // NaN 只要出现非有效数字的字符结果都是NaN
console.log(Number(true)); // 1
console.log(Number(false));  // 0
console.log(Number(null));  // 0
console.log(Number(undefined));  // NaN 将undefined转为number类型是 NaN
// console.log(Number(Symbol(1))); // 报错 不能将Symbol转为Number类型
console.log(Number(BigInt(1)));  // 1
// 对象转为数字,应该先valueOf,如果没有原始值再toString变为字符串,最后再把字符串转为数字

/* 
 * paresInt机制:
    从字符串左侧开始,查找有效数字字符,一旦在查找的过程中遇到非有效数字,则停止查找(不论后面是否还有有效数字),并返回已经找到的所有有效数字,如果找到最后都没有找到一个有效数字字符,则返回 NaN。
  
  * parseFloat机制跟parseInt差不对,只不过是比它多识别了一个小数点
*/

// isNaN(val):是隐式转换,会先把val转为数字,再给出结果是true还是false
 console.log(parseInt('')); // NaN
console.log(Number(''));   // 0
console.log(isNaN(''));    // false
console.log(parseInt(null)); // NaN
console.log(Number(null));  // 0
console.log(isNaN(null));   // false isNaN(0)
console.log(parseInt('12px')); // 12
console.log(Number('12px'));  // NaN
console.log(isNaN('12px'));   // true  isNaN(NaN)
console.log(parseFloat('1.6px')+parseInt('1.2px')+typeof parseInt(null)); // 2.6number
console.log(isNaN(Number(!!Number(parseInt('0.8'))))); // false
console.log(typeof !parseInt(null) + !isNaN(null)); // booleantrue typeof 优先级高于 +
// => boolean + !isNaN(null)
// => booleantrue

let result = 10 + false + undefined + [] + 'Tencent' + null + true +{};
        // 10 + 0 + NaN + '' + 'Tcentent'+null+true+'[object object]'
// []转为数字之前先转为字符串"",加号遇到字符串就变成字符串拼接了
// 字符串+{} :把{}转为字符串后进行拼接,{}转为字符串为 "[object object]"
console.log(result); // NaNTcententnulltrue[object object] */

// 思考题
let arr = [10.18, 0, 10, 25, 23];
arr = arr.map(parseInt);
/* 
 map(callBack):循环遍历数组中的内一项都会触发其回调函数,且每一次还会传递当前值和当前值的索引
 parseInt(string, [redix]):
   redix:可选,是一个进制,范围在2~36之间。
          如果不写或者为0,则按照十进制来处理;如果是以"0x"或者"0X"开头,则以16进制处理;
          如果该值小于2或者大于36,则parseInt()返回 NaN
  aee.map(parseInt) 等价于
    => parseInt('10.18', 0);  =>十进制处理 => 10
    => parseInt('0', 1);  // => 进制小于2 => NaN
    => parseInt('10', 2); // => 10(基于二进制找到的有效数字) => 1*2^1 + 0*2^0
    => parseInt('25', 3); // =>2(基于三进制找到的有效数字) => 2*3^0
    => parseInt('23', 4); // =>23(基于四进制找到的有效数字) => 3*4^0 + 2*4^1
*/
console.log(arr); // [10, NaN, 2, 2, 11]

变量提升

/* 
 * 变量提升:在当前上下文中(全局、私有、块级),JS代码自上而下会提前处理一些事情(可以理解为词法解析的一个环节,词法解析一定发生在代码执行之前)
    会把当前上下文中用 var/function 关键字创建的变量进行提前声明或者定义
      var a = 10;
      声明: var a;
      定义: a = 10
    用 var 创建的会提前声明
    用 function 创建的会提前声明加定义
*/

/* 
 * 代码执行之前:全局上下文中的变量提升(变量)
     var a; 默认值的 undefined
*/
/* console.log(a); // a已经被提前声明了,但是没有定义 =>undefined
var a = 12;  // 创建值12,不需要在声明a了(变量提升阶段完成了,完成的事情不会重新处理) a = 12 进行赋值
a = 13; // 创建值13 赋值给a
console.log(a); // 13 */

/*                                                              
 * 代码执行之前:全局上下文中的变量提升(函数)
      fn = 函数   函数在变量提升阶段会进行声明加定义
*/
 fn(); // 'OK'
function fn() {
  console.log('OK');
}
 

// fun(); // 变量提升阶段只定义,没有声明,所以 fun 是undefined
// =>报错 Uncaught TypeError: fun is not a function
/* var fun = function() {
  // 真实项目中建议用函数表达式创建函数,因为这样在变量提升阶段只会声明fun,并不会进行定义,所以没办法在函数定时之前进行调用
  console.log('OK');
}
fun(); // 'OK' */


 var fun = function AA() {
  // 把原本作为值的函数表达式的匿名函数“具名化”(就是给函数取了一个名字-- AA)
  // 具名化的函数名属于私有变量,只能在该执行上下文中只用
  console.log(AA);  // =>输出当前函数
  console.log(fun === AA); // => ture
  // AA(); // 可以实现递归调用(注意避免死递归)
}
// AA(); // 报错:AA is not defined
fun(); 
 


/* console.log(a); //报错:a is not defined  因为不是用 var/function声明的,所以不会发生变量提升
a = 13; */


/* console.log('OK'); // => 'OK'
console.log(a); // 报错 Cannot access 'a' before initialization 不能在创建变量a之前引用
let a = 13; */



/* 
 * EC(G): 全局上下文中的变量提升
      不论条件是否成立,都要进行变量提升(细节点:条件中带function的在新版本浏览器中只会提前声明,不会在提前定义(赋值)了)

*/
 console.log(a, fun) // undefined undefined
if(!('a' in window)) {
  var a = 1;
  function fun(){}
}
console.log(a); // unfeined 
// -------练习题----------
fn();  // =>5
function fn() {
  console.log(1);
}
fn();  // =>5
function fn() {
  console.log(2);
}
fn();  // =>5
var fn = function(){console.log(3)};
fn();  // => 3
function fn() {
  console.log(4);
}
fn();  // =>3
function fn(){
  console.log(5);
}
fn();  // => 3 
var foo = 1;
function bar() {
  if(!foo) {
    var foo = 10;
  }
  console.log(foo);  // 10
}
bar(); 
/* 
 * 解析:执行bar形成一个新的执行上下文
    变量提升(不论条件是否成立):var foo(默认值是undefined)
    形参赋值: 无
    代码执行:if(!undefined){foo = 10} 成立
             输出 foo => 10
整个bar上下文中用到的foo是私有的,跟全局的没有关系
*/

// ----思考题-----------
 var foo = 1;
function bar() {
  if(false) {
    var foo = 10;
  }
  console.log(foo); 
}
bar(); 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值