空数组为真,但也等于假。
Var arr = []; console.log(数组:,arr); if (arr) console.log("这是真的!"); if (arr == false) console.log("这是假的!"); 如果(arr & & arr = = false) console.log(“……什么? ?”);
我猜这是由于由等式运算符进行的隐式转换。
有人能解释一下幕后发生了什么吗?
空数组为真,但也等于假。
Var arr = []; console.log(数组:,arr); if (arr) console.log("这是真的!"); if (arr == false) console.log("这是假的!"); 如果(arr & & arr = = false) console.log(“……什么? ?”);
我猜这是由于由等式运算符进行的隐式转换。
有人能解释一下幕后发生了什么吗?
当前回答
你可以通过引用一个新的数组来清空JavaScript数组,使用list =[]或者删除当前引用数组列表中的元素。Length = 0。
来源:JavaScript空数组
其他回答
在if (arr)中,如果arr是一个对象,它总是被求值(ToBoolean)为true,因为JavaScript中的所有对象都是true。(null不是一个对象!)
[] == false采用迭代法求值。首先,如果==的一边是原语,另一边是object,它首先将object转换为原语,然后如果两边都不是字符串,则将两边都转换为Number(如果两边都是字符串,则使用字符串比较)。因此,比较是这样迭代的,[]== false -> " == false -> 0 == 0 -> true。
似乎没有人谈论原因 (arr && arr == false)为真。只是为了不确定运算符优先级的人,根据MDN, ==的优先级高于&&,所以它实际上是(arr && (arr == false))。在通配符的答案之后,它是真&&真,所以它是真。
Var arr = []; 如果(arr & & arr = = false) console.log(“……什么? ?”);
console.log('-- types: undefined, boolean, number, string, object --');
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof NaN); // number
console.log(typeof false); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof []); // object
console.log(typeof {}); // object
console.log('-- Different values: NotExist, Falsy, NaN, [], {} --');
console.log('-- 1. NotExist values: undefined, null have same value --');
console.log(undefined == null); // true
console.log('-- 2. Falsy values: false, 0, "" have same value --');
console.log(false == 0); // true
console.log(false == ""); // true
console.log(0 == ""); // true
console.log('-- 3. !NotExist, !Falsy, and !NaN return true --');
console.log(!undefined); // true
console.log(!null); // true
console.log(!false); // true
console.log(!""); // true
console.log(!0); // true
console.log(!NaN); // true
console.log('-- 4. [] is not falsy, but [] == false because [].toString() returns "" --');
console.log(false == []); // true
console.log([].toString()); // ""
console.log(![]); // false
console.log('-- 5. {} is not falsy, and {} != false, because {}.toString() returns "[object Object]" --');
console.log(false == {}); // false
console.log({}.toString()); // [object Object]
console.log(!{}); // false
console.log('-- Comparing --');
console.log('-- 1. string will be converted to number or NaN when comparing with a number, and "" will be converted to 0 --');
console.log(12 < "2"); // false
console.log("12" < "2"); // true
console.log("" < 2); // true
console.log('-- 2. NaN can not be compared with any value, even if NaN itself, always return false --');
console.log(NaN == NaN); // false
console.log(NaN == null); // false
console.log(NaN == undefined); // false
console.log(0 <= NaN); // false
console.log(0 >= NaN); // false
console.log(undefined <= NaN); // false
console.log(undefined >= NaN); // false
console.log(null <= NaN); // false
console.log(null >= NaN); // false
console.log(2 <= "2a"); // false, since "2a" is converted to NaN
console.log(2 >= "2a"); // false, since "2a" is converted to NaN
console.log('-- 3. undefined can only == null and == undefined, and can not do any other comparing even if <= undefined --');
console.log(undefined == null); // true
console.log(undefined == undefined); // true
console.log(undefined == ""); // false
console.log(undefined == false); // false
console.log(undefined <= undefined); // false
console.log(undefined <= null); // false
console.log(undefined >= null); // false
console.log(0 <= undefined); // false
console.log(0 >= undefined); // false
console.log('-- 4. null will be converted to "" when <, >, <=, >= comparing --');
console.log(12 <= null); // false
console.log(12 >= null); // true
console.log("12" <= null); // false
console.log("12" >= null); // true
console.log(0 == null); // false
console.log("" == null); // false
console.log('-- 5. object, including {}, [], will be call toString() when comparing --');
console.log(12 < {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log(12 > {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log("[a" < {}); // true, since {}.toString() is "[object Object]"
console.log("[a" > {}); // false, since {}.toString() is "[object Object]"
console.log(12 < []); // false, since {}.toString() is "", and then converted to 0
console.log(12 > []); // true, since {}.toString() is "", and then converted to 0
console.log("[a" < []); // false, since {}.toString() is ""
console.log("[a" > []); // true, since {}.toString() is ""
console.log('-- 6. According to 4 and 5, we can get below weird result: --');
console.log(null < []); // false
console.log(null > []); // false
console.log(null == []); // false
console.log(null <= []); // true
console.log(null >= []); // true
当我尝试使用knockout.js映射插件时,上述方法都没有帮助我,也许是因为“空数组”并不是真的空。
我最终使用:data-bind="if: arr()。长度”,这就成功了。
这是专门针对knockout的,不是OP的问题,但也许它会帮助其他在类似情况下浏览这里的人。
为了补充Wayne的回答,并尝试解释为什么ToPrimitive([])返回“”,值得考虑“why”问题的两种可能类型的答案。第一种回答是:“因为规范说JavaScript就是这样运行的。”在ES5规范第9.1节中,将ToPrimitive的结果描述为对象的默认值:
通过调用对象的[[DefaultValue]]内部方法来检索对象的默认值,并传递可选提示PreferredType。
Section 8.12.8 describes the [[DefaultValue]] method. This method takes a "hint" as an argument, and the hint can be either String or Number. To simplify the matter by dispensing with some details, if the hint is String, then [[DefaultValue]] returns the value of toString() if it exists and returns a primitive value and otherwise returns the value of valueOf(). If the hint is Number, the priorities of toString() and valueOf() are reversed so that valueOf() is called first and its value returned if it's a primitive. Thus, whether [[DefaultValue]] returns the result of toString() or valueOf() depends on the specified PreferredType for the object and whether or not these functions return primitive values.
默认的valueOf() Object方法只返回对象本身,这意味着除非类重写默认方法,否则valueOf()只返回对象本身。这就是Array的情况。[]. valueof()返回对象[]本身。由于Array对象不是原语,[[DefaultValue]]提示是不相关的:数组的返回值将是toString()的值。
引用David Flanagan的《JavaScript: The Definitive Guide》,顺便说一句,这是一本很棒的书,应该是每个人获得这类问题答案的首选之地:
The details of this object-to-number conversion explain why an empty array converts to the number 0 and why an array with a single element may also convert to a number. Arrays inherit the default valueOf() method that returns an object rather than a primitive value, so array-to-number conversion relies on the toString() method. Empty arrays convert to the empty string. And the empty string converts to the number 0. An array with a single element converts to the same string that that one element does. If an array contains a single number, that number is converted to a string, and then back to a number.
The second type of answer to the "why" question, other than "because the spec says", gives some explanation for why the behavior makes sense from the design perspective. On this issue I can only speculate. First, how would one convert an array to a number? The only sensible possibility I can think of would be to convert an empty array to 0 and any non-empty array to 1. But as Wayne's answer revealed, an empty array will get converted to 0 for many types of comparisons anyway. Beyond this, it's hard to think of a sensible primitive return value for Array.valueOf(). So one could argue that it just makes more sense to have Array.valueOf() be the default and return the Array itself, leading toString() to be the result used by ToPrimitive. It just makes more sense to convert an Array to a string, rather than a number.
此外,正如Flanagan所暗示的那样,这种设计决策确实能够实现某些类型的有益行为。例如:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
此行为允许您将单个元素数组与数字进行比较,并获得预期的结果。