从一道题引发的思考

172 阅读4分钟

今天从一个群里,看到这样一个题目:

console.log(([])?true:false);  
console.log(([]==false?true:false)); 
console.log(({}==false)?true:false); 

请问输出的结果是什么?

首先,对于第一道题

([])?true:false; // true

这个比较显而易见,是将 空数组[]转为Boolean(布尔)类型,因为 数组是一个对象,所以可以拓展为 对于任意的对象

在javascript中,只有以下情况 转为Boolean类型才返回false

undefined,
null,
0,
-0,
NaN,
"" //空字符串

其他情况 都返回 true

所以,Boolean(对象) 返回的 true,即 这道题的答案是 true

其次,对于第二题和第三题 涉及到 “==”运算符,以及对象的转换

“==”运算符,可以理解为 将 运算符两边 转为 数字 再进行比较

  • 数字 转为 数字 仍是 数字
Number(1);// 1
Number(0);// 0
  • 字符串 转为数字
  1. 如果 字符串中 存在不是数字的 那么 都为 NaN;
  2. 空字符串 转为数字 为 0
Number("12"); // 12
Number("12a");// NaN
Number("") ;//0    空字符串 转为 数字 为 0 
  • undefined /NaN 转为 数字 为 NaN
Number(undefined);// NaN
  • 布尔类型 转为 数字
  1. true转为 1
  2. false转为 0
Number(true);//1
Number(false);//0
  • Null 转为数字 为 0
  • 对象转为数字,也是最重要的部分,(将对象转为原始值)

所谓原始值,就是基本的数据类型

  1. 如果对象具有valueOf()方法,返回一个原始值,则JavaScript将这个原始值转换为数字(如果需要的话)并返回一个数字
  2. 当对象没有valueOf 或者 返回的不是一个原始值。那么 如果对象具有toString()方法,返回一个原始值,则JavaScript将其转换并返回。(对象的toString()方法返回一个字符串直接量,JavaScript将这个字符串转换为数字类型,并返回这个数字)
  3. 否则,JavaScript抛出一个类型错误异常。 Number(obj);可以简单的理解为一下几个步骤: 第一步 : 调用 obj.valueOf() 方法 ,返回结果 如果是 原始值,那么 Number(原始值) 第二步: 否则,调用 obj.toString()方法,返回结果如果是 原始值,那么Number(原始值) 第三步: 否则,抛出异常
// 对象 的valueOf 和 toString 返回的都是 原始值
// 先调用 valueOf 如果 返回的是原始值,那么就直接返回
let obj = {
    valueOf:function(){
        return 123;  
    },
    toString:function(){
        return 231;
    }
}

Number(obj); // 则为 123 
// 对象 的valueOf 返回的是不是原始值 而 toString 返回的是 原始值

// 如果valueOf返回的不是原始值 ,那么 则会调用 对象的toString
let obj = {
    valueOf:function(){
        return new Object();
    },
    toString:function(){
        return 231;
    }
}

console.log(Number(obj));
// 对象 的valueOf 和 toString 返回的 都不是 原始值
let obj ={
    valueOf:function(){
     return  new Object();
   },
    toString:function(){
     return new Object();
    }
}

Number(obj);
// TypeError: Cannot convert object to primitive value  
// 无法将 对象 转为 原始值

数组 转为 数字 分析:

let arr = new Array();
//arr.valueOf(); 返回的依旧是 数组 所以会调用  toString
//arr.toString(); 数组的toString 方法返回的是 字符串, 可以 看成 使用了 arr.join(",")
// 返回的 是以  ","分开的 字符串 

let arr2 = []; //空数组
Number(arr2) ;// 返回的是 0 ; 过程  空数组 -> 空字符 -> 0


let arr3 = [1,2,3]Number(arr3);
// 返回的是 NaN ; 过程  [1,2,3] -> 字符串:1,2,3 -> NaN (字符串中存在非数字的",")
 

“==”运算符,两边的数据类型不一样

  • 如果一个 为null,另一个为undefined ,那么 他们相等
  • 如果一个为数字,另一个为字符串,那么将字符串转为数字,然后对转换后的数值进行比较
  • 如果其中一个为true,那么将true转为1,再进行数值比较
  • 如果其中一个为false,那么将false转为0,再进行数值比较
  • 如果其中一个为对象,另一个为数字或者字符串,那么将对象转换为原始数值,在进行比较

所以题目的答案是

console.log(([])?true:false); // true
console.log(([]==false?true:false)); //true
console.log(({}==false)?true:false); // false

解析:

  • 第一题:将数组 -> Boolean,参考上面,除了 undefined,null,false,0,空字符,null,NaN返回false,其他都返回true ,并且 对象返回的 都是 true;所以 为true
  • 第二题:首先将数组 -> 数字, 如果是空数组 转为 0 ;同时 false 转为 数字 为0 ,则 两边相等 ,所以为 true
  • 第三题:空对象 -> 数字 ,首先调用valueOf ,返回 依旧是 对象 , 所以 会调用 toString()方法, 对象返回的是 "[object Object ]" 转为数字 为NaN ,两边不相等,则为 false,所以 为 false