先上代码:
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来实现继承。
如果有错误或者不严谨的地方,请给予指正,十分感谢!