第47题 JS易错题

. VS = 操作符优先级

    let a = {n : 1};
    let b = a;
    a.x = a = {n: 2};
    
    
    console.log(a.x)
    console.log(b.x)

输出是什么呢?

答案

    // undefined 
    // { n : 2}

作用域

    var a = 0,  
    b = 0;
    function A(a) {
      A = function (b) {
        console.log(a + b++)
      }
      console.log(a++)
    }
    A(1)
    A(2)
```**答案**

**答案 1 4**

### 类数组的length
```js
    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)

这段代码的执行结果?

答案

    Object(4) [empty × 2, 1, 2, splice: ƒ, push: ƒ]

  • 解释就是第一次使用push,obj对象的push方法设置obj[2] = 1,obj.length++
  • 解释就是第一次使用push,obj对象的push方法设置obj[3] = 2,obj.length++
  • 使用console.log()方法输出的时候,因为obj上有length属性和splice方法,故将其作为数组输出打印
  • 打印时因为数组未设置下标为0和1的值,故打印的结果就是empty,主动获取obj[0] = undefined

非匿名自执行函数,函数名只读

    var b = 10;
    (function b(){
      // 'use strict'
      b = 20
      console.log(b)
    })()

输出的结果是什么?

答案

    Function b
  • 如标题一样,非匿名自执行函数,函数名不可以修改,严格模式下会TypeError
  • 非严格模式下,不报错,修改也没有用。
  • 查找变量b时,立即执行函数会有内部作用域,会先去查找是否有b变量的声明,有的话,直接复制
  • 确实发现具名函数Function b(){} 所以就拿来做b的值
  • IIFE的函数内部无法进行复制(类似于const)

非匿名自执行函数2

    var b = 10;
    (function b(){
      // 'use strict'
      var b = 20
      console.log(window.b) 
      console.log(b)
    })()

输出是多少呢?

答案

    10
    20
    // 访问b变量的时候,发现var b = 20;在当前作用域中找到了b变量,于是把b的值作为20

非匿名自执行函数3

    var b = 10;
    (function b(){
        console.log(b)
        b = 5
        console.log(window.b)
        var b = 20
        console.log(b)
    })()

输出的结果是多少呢?

变量提升

    var name = 'World!';
    (function () {
        if (typeof name === 'undefined') {
            var name = 'Jack';
            console.log('Goodbye ' + name);
        } else {
            console.log('Hello ' + name);
        }
    })();

在 JavaScript中, Fun 和 var 会被提升

相当于

    var name = 'World!';
    (function () {
        var name;
        if (typeof name === 'undefined') {
            name = 'Jack';
            console.log('Goodbye ' + name);
        } else {
            console.log('Hello ' + name);
        }
    })();

巩固一下:

    var str = 'World!';   
    (function (name) {
      if (typeof name === 'undefined') {
          var name = 'Jack';
          console.log('Goodbye ' + name);
      } else {
          console.log('Hello ' + name);
      }
    })(str);
```**答案**

> 答案:Hello World 因为name已经变成函数内局部变量

### 数组的原型是什么
```js
    Array.isArray( Array.prototype )

这段代码的执行结果?

答案

  • 答案:true
  • 解析:Array.prototype是一个数组
  • 数组的原型是数组,对象的原型是对象,函数的原型是函数

数组比较大小

    var a = [1, 2, 3],
        b = [1, 2, 3],
        c = [1, 2, 4]
    a ==  b
    a === b
    a >   c
    a <   c

这段代码的执行结果?

答案

  • 答案:false, false, false, true
  • 解析:相等(==)和全等(===)还是比较引用地址。引用类型间比较大小是按照字典序比较,就是先比第一项谁大,相同再去比第二项。

原型

    var a = {}, b = Object.prototype;
    [a.prototype === b, Object.getPrototypeOf(a) === b] 

执行结果是多少呢

  • 答案:false, true
  • 解析:Object 的实例是 a,a上并没有prototype属性a的__poroto__指向的是Object.prototype,也就是Object.getPrototypeOf(a)。a的原型对象是b

原型II

    function f() {}
    var a = f.prototype, b = Object.getPrototypeOf(f);
    a === b         

这段代码的执行结果?

  • 答案:false
  • 解析:
    • a是构造函数f的原型 : {constructor: ƒ}
    • b是实例f的原型对象 : ƒ () { [native code] }

函数名称

    function foo() { }
    var oldName = foo.name;
    foo.name = "bar";
    [oldName, foo.name]     

代码执行结果是什么?

  • 答案:["foo", "foo"]
  • 解析:函数的名字不可变.

Function.length

    var a = Function.length,
    b = new Function().length
    a === b

这段代码的执行结果是?

  • 答案:false
  • 解析:
    • 首先new在函数带()时运算优先级和.一样所以从左向右执行
    • new Function() 的函数长度为0
  • 巩固:
    function fn () {
        var a = 1;
    }
    console.log(fn.length) 
    //0 fn和new Function()一样

"b" + "a" + +"a" + "a"

你认为输出是什么?

上面的表达式相当于'b'+'a'+ (+'a')+'a',因为(+'a')是NaN,所以:

    'b'+'a'+ (+'a')+'a' = 'b'+'a'+ "NaN"+'a'='baNaNa'

闭包

这是一个经典JavaScript面试题

    let res = new Array()
    for(var i = 0; i < 10; i++){
        res.push(function(){
            return console.log(i)
        })
    }
    res[0]() 
    res[1]()
    res[2]()

期望输出的是0,1,2,实际上却不会。原因就是涉及作用域 ,怎么解决呢?

  • [x] 使用let代替var,形成块级作用域
  • [x] 使用bind函数。
    res.push(console.log.bind(null, i))

解法还有其他的,比如使用IIFE,形成私有作用域等等做法。

又一经典闭包问题

    function fun(n,o) {
      console.log(o)
      return {
        fun:function(m){
          return fun(m,n);
        }
      };
    }
    var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);//undefined,?,?,?
    var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
    var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?

隐式转换

    var a = [0];
    if (a) {
      console.log(a == true);
    } else {
      console.log("wut");
    }

你们觉得答案是多少呢?

    // 答案:false

再来一道?

    function fn() {
        return 20;
    }
    console.log(fn + 10); // 输出结果是多少
    function fn() {
        return 20;
    }
    fn.toString = function() {
        return 10;
    }
    console.log(fn + 10);  // 输出结果是多少?
    function fn() {
        return 20;
    }
    
    fn.toString = function() {
        return 10;
    }
    
    fn.valueOf = function() {
        return 5;
    }
    
    console.log(fn + 10); // 输出结果是多少?

一道容易被人轻视的面试题

    function Foo() {
        getName = function () { alert (1); };
        return this;
    }
    Foo.getName = function () { alert (2);};
    Foo.prototype.getName = function () { alert (3);};
    var getName = function () { alert (4);};
    function getName() { alert (5);}
    
    //请写出以下输出结果:
    Foo.getName();
    getName();
    Foo().getName();
    getName();
    new Foo.getName();
    new Foo().getName();
    new new Foo().getName();

let var

    function foo() {
    let a = b = 0;
    a++;
    return a;
    }
    foo();
    typeof a; // => ???
    typeof b; // => ???

上面的let a = b = 0; 等价于 window.b = 0, let a = b;

眼力题

    const length = 4;
    const numbers = [];
    for (var i = 0; i < length; i++);{
      numbers.push(i + 1);
    }
    
    numbers; // => ???

唯一需要注意的就是for语句后面带了;沙雕题

加了;,会认为for执行完,所以指定的都是空语句,最后numbers为[5]

Last Updated:
Contributors: leeguooooo