|

数据类型转换的那些坑:隐式类型转换

本文的讨论数据类型转换主要是指应用在逻辑判断中存在的转换,这种转换也被成为 JavaScript 的隐式类型转换,隐式类型转换可能会带来与逻辑预期不符的结果,所以需要明确这其中的坑。

if 判断

NaN、0、null、undefined、“” => false

开发中经常需要对某个值做 if 判断,然后决定需要执行的代码分支,在使用 if 判断时,可能会出现一些不符合主观预期的结果,例如:

let arr = []
if (arr) {
    console.log("hello");
}
// hello

以上代码的 if 判断主观上可能认为是 false ,然而结果却是 true,所以打印出了 hello 。

在使用 if 进行判断时,表达式如果为单一值或者变量, 那么只有下列情况会返回 false:

  • NaN
  • 0
  • null
  • undefined
  • “”(空字符串)
  • false

除了以上情况外,其他都会返回 true ,所以下面的代码也是会按照 if (true) 来输出:

let a = [];
let b = {};

if (a) console.log('a');            // a
if (b) console.log('b');            // b
if (a && b) console.log('a && b');  // a && b

所以直接使用 if 来判断数组是否为空或者对象是否为空是不可靠的,编程时需要明确知道这里判断的到底是什么。

之所以会出现上面的问题,是由于 if 逻辑判断的表达式,最后是一个布尔值,所以会隐式转换为 Boolean 类型来判断,所以上面的代码相当于:

let a = [];
let b = {};

if (Boolean(a)) console.log('a');           // a
if (Boolean(b)) console.log('b');           // b
if (Boolean(a) && Boolean(b)) console.log('a && b');    // a && b

同理,空对象和空数组隐式转换为 Boolean 的结果为 true,所以下面的代码会输出 true:

console.log(Boolean([]));       // true
console.log(Boolean({}));       // true

等于 与 完全等于

这是两个符号,等于()与 完全等于(=)。

使用 等于 进行逻辑判断时,也会出现不符合预期的结果,例如:

console.log(null == undefined); // true

而使用 完全等于 则可以得到符合预期的结果:

console.log(null === undefined);    // false

这是由于 = 判断的方式不同, 仅判断值是否相等,而 = 不仅判断值是否相等,也会判断类型是否相等。

等于

使用等于好做判断时是判断值是否相等,即表示要做一个隐式类型转换,转为的结果为 number

所以,下面的两行代码应该是等价的:

console.log(null == 0);         // true
// 等价于下面的代码
console.log(Number(null) == 0); // true

同理,下面的代码也是等价的:

console.log([] == 0);           // true
// 等价于下面的代码
console.log(Number([]) == 0);   // true

所以, 等于的具体判断过程为:

  • 两个对象的类型是否相同,如果相同,则直接对比值是否相同;
  • 如果两个对象的类型不同,则先进行隐式转换,转为 Number 类型,然后判断值是否相同;

需要补充的一点是,如果两个比较对象的类型不同,且分别为 nullundefined ,则直接返回 true ,不在进行隐式类型转换。

于是可知,下面的判断将返回 false :

console.log(undefined == {});       // false

因为在隐式转换中,undefined 和 空对象 {} 无法转换为有意义的 Number 值,对 undefined 和 {} 的 Number 转换都将得到 NaN ,而 NaN 与任何值比对都将为 false ,即:

console.log(Number(undefined));     // NaN
console.log(Number({}));            // NaN
console.log(NaN == NaN);            // false

完全等于 =

完全等于与等于不同的是,使用完全等于进行判断时会进行值和类型的同时判断,如果类型不同则不会进行隐式类型转换,所以可以得到符合预期的严格结果。

所以,= 完全等于的判断过程为:

  • 如果比较对象的类型不同,则为 false ;
  • 如果比较对象的类型相同,但是值不同,依然为 false;

基于上述过程,下面的代码应该是好理解的:

console.log(null === undefined);        // false

由于 null 和 undefined 是两个不同的基本类型,所以首先就类型不同了,也就没有必要比较值,结果当然为 false。

需要注意一点,下面的比较也将返回 false :

console.log(NaN === NaN);       // false

这是由于 NaN 可以为任意值,所以 NaN 与任何值比较的结果都为 false ,也包括 NaN 自己。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注