题目及答案:
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
此题涉及的知识点众多,包括变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级等等。
此题包含7小问,分别说下。
第一问:
先看此题的上半部分做了什么,首先定义了一个叫Foo的函数,之后为Foo创建了一个叫getName的静态属性存储了一个匿名函数,之后为Foo的原型对象新创建了一个叫getName的匿名函数。之后又通过函数变量表达式创建了一个getName的函数,最后再声明一个叫getName函数。
第一问的 Foo.getName 自然是访问Foo函数上存储的静态属性,自然是2,没什么可说的。
接下来看第二问:
这里需要知道的点就是,变声的提升(函数表达式)和函数的声明提升的不同;
变量的提升(函数表达式)是将var x提升到代码的最顶层去,而将赋值操作留在“原地不动”,当代码执行到赋值操作的位置时,再进行赋值操作。
函数的提升是将整个的命名函数都提升到函数的顶层。
(这里就是变量的变量名字提升了,与它同名的声明函数也提升到了顶层,当代码执行到了变量赋值的时候,函数表达式(var getName = function () { alert (4);};)的赋值操作将再次覆盖掉之前命名函数的赋值操作。所以第二问答案是4)
然后看第三问:Foo().getName()
首先执行的是Foo函数,Foo函数的第一句 getName = function () { alert (1); }; 是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为 function(){alert(1)}。
第四问:由于第三问已经对getName()进行了赋值操作,所以答案也是1
网友评论