前言
问题场景:
在做一个后台返回数据是否有值的处理操作时,用if判断发现的一个有意思的问题
代码如下:
后台返回数据即:res.data.list = []
if(res.data.list == []){
console.log('无数据返回')
}
else
{
console.log('有数据')
}
打印结果:有数据
问题引申
发现这个问题后就做了一些测试,测试代码如下:
console.log("Boolean([]):",Boolean([]),"Boolean(![]):",Boolean(![]))
//Boolean([]): true Boolean(![]): false
console.log("[]==[]:",[]==[],"![]==[]",![]==[])
// []==[]: false ![]==[] true
console.log("+[]==[]:",+[]==[],"!(+[])==[]",!(+[])==[])
// +[]==[]: true !(+[])==[] false
console.log("-[]==[]:",-[]==[],"!(-[])==[]",!(-[])==[])
// -[]==[]: true !(-[])==[] false
console.log("[]==true:",[]==true,"[]==false:",[]==false)
// []==true: false []==false: true
console.log("![]==true:",![]==true,"![]==false:",![]==false)
// ![]==true: false ![]==false: true
要点一
falsy(假值)、truthy(真值)
falsy(假值): 在 JavaScript 中只有 7 个 falsy 值。
false false 关键字
0 数值 zero
0n 当 BigInt 作为布尔值使用时, 遵从其作为数值的规则. 0n 是 falsy 值.
"", '', `` 这是一个空字符串 (字符串的长度为零). JavaScript 中的字符串可用双引号 "", 单引号 '', 或 模板字面量 `` 定义。
null null - 缺少值
undefined undefined - 原始值
NaN NaN - 非数值
truthy(真值):
在 JavaScript 中,truthy(真值)指的是在布尔值上下文中,转换后的值为真的值。
所有值都是真值,除非它们被定义为 假值(即除 false、0、""、null、undefined 和 NaN 以外皆为真值。
要点二
首先:数组的原型中有(继承了)对象原型!---不知道这么说合不合适
布尔操作符 --> ! 逻辑非
逻辑非操作符首先会将它的操作数转换为布尔值,然后再对其求反。
如果操作数是一个对象,返回 false;
如果操作数是一个空字符串,返回true;
如果操作数是一个非空字符串,返回false;
如果操作数是数值0,返回true;
如果操作数是任意非0数值(包括Infinity),返回false;
如果操作数是null,返回true;
如果操作数是NaN,返回true;
如果操作数是undefined,返回true;
列:
alert(!false); //true
alert(!"blue");//false
alert(!0); //true
alert(!NaN); //true
alert(!""); //true
alert(!12345);//false
相等操作符 --> ==
相等操作符(==),如果两个操作数相等,则返回true。
相等和不想等操作符都会先转换操作数(通常称为强制转型),然后再比较他们的相等性;
*.在转换不同的数据类型时,相等和不想等操作符遵循以下规则:
>如果一个操作数时布尔值,则在比较相等性之前先将其转换为数值---false转换为0,true转换为1;
>如果一个操作数是字符申,另个操作数是数值, 在比较相等性之前先将字符串转换为数值;
>如果一个撵作数是对象,另一个操作数不是,
则调用对象的valueOf()方法(如果没有得到基本类型-->[],则调用对象的toString()方法-->""),
用得到的基本类型值按照前面的规则进行比较;
*.这两个操作符在进行比较时则要遵循下列规则:
>与null和undef ined是相等的。
>要比较相等性之前,不能将null和undefined转换成其他任何值。
>如果有一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true;
重要提示:即使两个操作数都是NaN,相等操作符也返回false;
因为按照规则,NaN不等于NaN。
>如果两个操作数都是对象,则比较它们是不是同一个对象。
如果两个操作数都指向同一个对象,则相等操作符返回true;否则,返回false.
总结
let model = []
console.log(model,model.toString())
//[],""
/**
* []转换Boolean型时,回把[]看作一个对象,即任何对象转为Boolean型 ,返回 true
* !在操作对象时返回false
*/
console.log("Boolean([]):",Boolean([]),"Boolean(![]):",Boolean(![]))
//Boolean([]): true Boolean(![]): false
/**
* []==[] 看作为两个对象之间的相等操作比较 --> 不是同一个对象--> false
* ![]==[] 首先 左边 布尔操作符![]-->!true-->false
* 右边分析--> []看作为对象 调用valueOf()没有得到基本类型,调用toString()方法--> "" --> 空字符串转换布尔型为 false
* 结果 false == false -->
* 如果一个操作数时布尔值,则在比较相等性之前先将其转换为数值 --> 0 == 0 --> true
*/
console.log("[]==[]:",[]==[],"![]==[]",![]==[])
// []==[]: false ![]==[] true
/**
* 左边分析--> +[]看作为对象 调用toString()方法--> +"" --> 0
* 右边 --> [] --> 调用valueOf()没有得到基本类型,调用toString()方法--> "" --> 空字符串转换布尔型为 false
* 如果一个操作数时布尔值,则在比较相等性之前先将其转换为数值 --> 结果 0 == false
* 如果一个操作数时布尔值,则在比较相等性之前先将其转换为数值 --> 0 == 0 --> true
*/
console.log("+[]==[]:",+[]==[],"!(+[])==[]",!(+[])==[])
// +[]==[]: true !(+[])==[] false
/**
* 左边分析--> -[]看作为对象 调用toString()方法--> -"" --> -0
* 右边 --> [] --> 调用valueOf()没有得到基本类型,调用toString()方法--> "" --> 空字符串转换布尔型为 false
* 如果一个操作数时布尔值,则在比较相等性之前先将其转换为数值 --> 结果 0 == false --> -0 == 0 --> true
*/
console.log("-[]==[]:",-[]==[],"!(-[])==[]",!(-[])==[])
// -[]==[]: true !(-[])==[] false
/**
* 左边分析--> []看作为对象 调用valueOf()没有得到基本类型,调用toString()方法--> ""
* 即 "" == true
* 如果一个操作数时布尔值,则在比较相等性之前先将其转换为数值 --> 0 == 1 --> false
* "" == false --> 0 == 0 --> true
*/
console.log("[]==true:",[]==true,"[]==false:",[]==false)
// []==true: false []==false: true
/**
* ![] 布尔操作符![]-->!true-->false
* 结果 false == true --> 0 == 1 --> false
* 结果 false == false --> 0 == 0 --> true
*/
console.log("![]==true:",![]==true,"![]==false:",![]==false)
// ![]==true: false ![]==false: true
结语
实际开发中要避免上述的隐试转换问题。
更有利于开发中代码的可读性。
但是又是一些比较基础的问题,面试可能会被问到。