再来两个小问题

299 阅读2分钟

先上代码:

function foo(){
  if (false) {
    function foo() {
      return 2;
    }
  }
console.log(foo());
}
foo(); 

以上代码会输出什么呢?

答案是foo is not a function

以上代码可以解释为如下代码:

function foo(){
  let foo;
  if (false) {
    foo = function() {
      return 2;
    }
  }
console.log(foo());
}
foo(); 

因为函数声明在条件为假的if语句里边,所以这个时候只是函数声明的提升,而并没有初始化该函数,所以此时foo是undefined,把它当做函数调用报错 is not a function

再来看另一个有意思的问题,代码如下:

let s = {
  a: function() {
      console.log(this);
  },
  b() {
      console.log(this);
  }
}
let foo = s.a.bind(this),
bar = s.b.bind(this);
console.log(new foo());
console.log(new bar());

以上代码又会输出什么呢?

答案是如下:

a {}
a {}
TypeError: bar is not a constructor

这里涉及到一些new做了什么,简单讲

1. 创建一个新对象

2. 执行构造函数的代码,并将this绑定到新创建的对象

3.将新创建对象的__proto___连接到构造函数的prototype

4.如果构造函数没有返回一个对象,则返回这个新创建的对象

基于此,也就理解了打印的两个a一个是执行构造函数代码时的console.log,一个是new 操作符的返回值,接下来要思考的是为什么new bar()的时候报错了呢?

这是因为ES6属性名简写的函数和箭头函数都是没有prototype的,所以会报错bar不是构造函数,那么为什么会这样设计呢?

这是因为属性名简写的函数作为一个对象的方法,而箭头函数在声明的时候就绑定了this,都不会作为构造函数来使用,而且ES6提倡大家放弃对构造函数的使用,而采用Class来实现继承。

如果有错误或者不严谨的地方,请给予指正,十分感谢!