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(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new new Foo().getName(); // 3
JavaScript 解释器中存在一种变量声明被提升的机制,也就是说函数声明会被提升到作用域的最前面,即使写代码的时候是写在最后面,也还是会被提升至最前面。而用函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用。
1、Foo.getName自然是访问Foo函数上存储的静态属性。
2、函数表达式覆盖函数声明。
3、先执行了Foo函数,然后调用Foo函数的返回值对象的getName属性函数。Foo函数的第一句getName = function () { alert (1); };是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为function(){alert(1)}。
此处实际上是将外层作用域内的getName函数修改了。
之后Foo函数的返回值是this,此处this指向window对象。
4、直接调用getName函数,相当于window.getName(),因为这个变量已经被Foo函数执行时修改了,所以结果与第三问相同,为1,也就是说Foo执行后把全局的getName函数给重写了一次,所以结果就是Foo()执行重写的那个getName函数。
5、new (Foo.getName)()
6、(new Foo()).getName()
7、new ((new Foo()).getName)();
延伸:
function Foo() {
this.getName = function() {
console.log(3);
return {
getName: getName//这个就是第六问中涉及的构造函数的返回值问题
}
};//这个就是第六问中涉及到的,JS构造函数公有方法和原型链方法的优先级
getName = function() {
console.log(1);
};
return this
}
Foo.getName = function() {
console.log(2);
};
Foo.prototype.getName = function() {
console.log(6);
};
var getName = function() {
console.log(4);
};
function getName() {
console.log(5);
} //答案:
Foo.getName(); //2
getName(); //4
console.log(Foo())
Foo().getName(); //1
getName(); //1
new Foo.getName(); //2
new Foo().getName(); //3
//多了一问
new Foo().getName().getName(); //3 1
new new Foo().getName(); //3