第二道题是关于作用域和提升的。
你应该知道声明都是会被提升的,即var声明跟function声明都会被提升到顶部。你也应该知道有两个操作,声明跟赋值,先声明再赋值。(不知道的话,就得好好在复习一下基础了。)
基本流程:
var a = 2;
首先var a声明一个a变量,初始化为undefined,提升到顶部,就像
var a;
a = 2;
两者是一个意思。然后再对a进行赋值。这有个过程
引擎:作用域,你见过a吗?
作用域:见过,编译器刚声明过这个a变量,拿去用吧!
引擎:好嘞,我给它赋值下。
你还得知道的是,函数优先提升。
var a = 2;
function a(){
console.log(1);
}
a//2
函数声明被优先声明到顶部,然后被变量声明覆盖!
好了,接下来看这道题
function Foo() {
getName = function () {
console.log('1');
};
return this;
}
Foo.getName = function () {
console.log('2');
};
Foo.prototype.getName = function () {
console.log('3');
};
var getName = function () {
console.log('4');
};
function getName() {
console.log(5);
}
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
首先我们可以看到,被提升的有函数声明Foo(),Foo.getName,Foo.prototype.getName,getName,函数声明getname()。
注意这里只是声明,没有赋值,只是让引擎能找到这些东西。
Foo.getName()引擎问作用域有这个吗?作用域回答有!然后就运行函数,Foo.getName(),输出2。
同理,getName()输出4;
Foo().getName()运行的时候在Foo()作用域中没有getName这个的声明,所以当引擎对getName进行赋值操作时,发现没有这个变量存在,没有是吗?没有就给你声明一个嘛,就立刻声明一个getName的全局变量(注意,覆盖了原先的全局变量getName)。这里输出1。
所以再次调用getName()的时候,它已经被Foo中的那个getName覆盖了,也输出1。
后面三题,我看到的时候奇怪了。虽然我知道new声明,但我之前接触的都是new 一个构造函数,这种new 一个“属性”的我还是第一次见。所以它到底是new 了个什么东西,我都搞不明白,还好原博主贴了张运算符优先级表(如下)
所以上面三个其实就是
new (Foo.getName)();
(new Foo()).getName();
new ((new Foo()).getName)();
第一个就是new 了个Foo.getName函数,所以输出的还是2;
第二个就是new了个Foo()然后调用getName方法,注意这里new后新对象是没有getName方法的,所以它要跟着原型链去找getName方法,就是调用Foo.prototype.getName,所以输出3;
第三个就是对第二个又new了一次,还是输出3。