JS 迷惑题大赏

点击答案,即可查看答案。

1、对象的引用

let a = {n : 1};
let b = a;
a.x = a = {n: 2};

console.log(a.x) // ?
console.log(b.x) // ?
答案:

输出:a.x => undefined b.x => {n:2}

解释:

1. a 被重新赋值为 { n:2 },没有 x 属性,所以输出 undefined;

2. a.x 是给原来 a 指向的对象即 { n:1 }添加了 x 属性,属性值为 { n:2 }。因为 b 也指向这个对象,因此 b.x 输出 { n:2 }

2、对象的引用Ⅱ

let a = { n: 1 };
let b = a;
b.n = a.f = { n: 2 };

console.log(a); // ?
console.log(b); // ?
答案:

输出:

// a
{ n: { n: 2 }, f: { n: 2 } }
// b 
{ n: { n: 2 }, f: { n: 2 } }

解释:

a添加了 f 属性,属性值为:{ n:2 };因为b和a指向同一个对象,所以,b也有了这个属性;同样的,b修改了n属性值,a也会跟着改变

3、push 做了什么

var obj = {
    "2" : 3,
    "3" : 4,
    "length" : 2,
    "splice" : Array.prototype.splice,
    "push" : Array.prototype.push
}
obj.push(1)
obj.push(2)

console.log(obj)
答案:

输出:[empty, empty, 1, 2]

解释:

1. push 方法相当于设置 obj[obj.length] = push的值,然后让 obj.length += 1。因为存在 splice 方法,所有输出形式是一个类数组,且长度为 4

4、声明函数的立即执行

var b = 10;
(function b(){
    b = 20;
    console.log(b) // ?
})();
答案:

输出:function b(){ ... }

解释:

在立即执行函数内部访问未经声明的变量,会优先查看是否是当前函数的函数名,而在非匿名自执行函数中,函数名为只读属性,无法被修改。


**变化一番:**
var b = 10;
(function b(){
    console.log(b) // ?
    b = 5
    console.log(window.b) // ?
    var b = 20
    console.log(b) // ?
})()
答案:

输出:undefined 10 20

解释:

因为函数内部有 var 声明,b变量提升,所以第一个b输出 undefined,第二次输出访问 window 上的b,输出 10,第三次输出函数中的 b,此时b已经赋值,故输出 20

5、相等的奥义

[] == ![]  // ?
答案:

输出:true

解释:

在JS中,两个等号的比较会优先转换值类型为统一类型,再进行值的比较。转换规则如下:

①、如果比较值有一个是布尔值,则在比较相等性之前先将比较的值转换为数字类型——false转换为0,而true转换为1;

②、如果比较值一个是字符串,另一个是数字,在比较相等性之前先将字符串转换为数字

③、如果比较值一个是对象,另一个不是,则调用对象的valueOf()方法,返回值按照前面的规则进行比较

上述表达式即:[] == false,使用①法则,二者变为Number类型都为 0,所以是相等的。


**雪上加霜:**
var a = [0];
if(a){
    console.log(a == true);
}else {
    console.log("what the fuck!");
}
// ?
答案:

输出:false

解释:

因为a是一个数组,转换为布尔值结果为 true,因此进入 if 语句条件为真的执行体;比较时使用规则 ①,[0] 转换为数字为 0, true 转换为数字为 1,因此不相等,返回false。

6、短路与三元

1 || 2 && 3; // ?
1 || 1 ? 2 : 3 // ?
答案:

输出:1 2

解释:

短路语句中 || 会优先输出真值,1转换为布尔值即为true,因此输出 1;第二个语句中三元运算式会根据前面的短路语句的返回值进行判断,1 为 true,所以返回 2

7、Math.minMath.max

Math.min() < Math.max() // ?
答案:

输出:false

解释:

因为 Math.min 不带参数的结果输出为 Infinity,而 Math.max 不带参数的结果输出为 -Infinity

8、不良代码书写习惯

function f()
{
    return {
        a: 10
    }    
}

function fn()
{
    return 
    {
        b: 10
    }
}

console.log(f()); // ?
console.log(fn()); // ?