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();getName();Foo().getName();getName();new Foo.getName();new Foo().getName();new new Foo().getName(); 这几天面试上几次碰上这道经典的题目,特地从头到尾来分析一次答案,这道题的经典之处在于它综合考察了面试者的JavaScript的综合能力,包含了变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级等知识,此题在网上也有部分相关的解释,当然我觉得有部分解释还欠妥,不够清晰,特地重头到尾来分析一次,当然我们会把最终答案放在后面,并把此题再改高一点点难度,改进版也放在最后,方便面试官在出题的时候有个参考,更多详情可关注本文作者@Wscats 第一问先看此题的上半部分做了什么,首先定义了一个叫Foo的函数,之后为Foo创建了一个叫getName的静态属性存储了一个匿名函数,之后为Foo的原型对象新创建了一个叫getName的匿名函数。之后又通过函数变量表达式创建了一个getName的函数,最后再声明一个叫getName函数。 第一问的Foo.getName自然是访问Foo函数上存储的静态属性,答案自然是2,这里就不需要解释太多的,一般来说第一问对于稍微懂JS基础的同学来说应该是没问题的,当然我们可以用下面的代码来回顾一下基础,先加深一下了解 function User(name) { var name = name; //私有属性 this.name = name; //公有属性 function getName() { //私有方法 return name; } } User.prototype.getName = function() { //公有方法 return this.name; } User.name = 'Wscats'; //静态属性 User.getName = function() { //静态方法 return this.name; } var Wscat = new User('Wscats'); //实例化 注意下面这几点:
第二问第二问,直接调用getName函数。既然是直接调用那么就是访问当前上文作用域内的叫getName的函数,所以这里应该直接把关注点放在4和5上,跟1
2 3都没什么关系。当然后来我问了我的几个同事他们大多数回答了5。此处其实有两个坑,一是变量声明提升,二是函数表达式和函数声明的区别。 函数声明// 函数声明 function wscat(type){ return type==="wscat"; } 函数表达式// 函数表达式 var oaoafly = function(type){ return type==="oaoafly"; } 先看下面这个经典问题,在一个程序里面同时用函数声明和函数表达式定义一个名为getName的函数 getName()//oaoafly var getName = function() { console.log('wscat') } getName()//wscat function getName() { console.log('oaoafly') } getName()//wscat 上面的代码看起来很类似,感觉也没什么太大差别。但实际上,Javascript函数上的一个“陷阱”就体现在Javascript两种类型的函数定义上。
var getName//变量被提升,此时为undefined getName()//oaoafly 函数被提升 这里受函数声明的影响,虽然函数声明在最后可以被提升到最前面了 var getName = function() { console.log('wscat') }//函数表达式此时才开始覆盖函数声明的定义 getName()//wscat function getName() { console.log('oaoafly') } getName()//wscat 这里就执行了函数表达式的值 所以可以分解为这两个简单的问题来看清楚区别的本质 var getName; console.log(getName)//undefined getName()//Uncaught TypeError: getName is not a function var getName = function() { console.log('wscat') } var getName; console.log(getName)//function getName() {console.log('oaoafly')} getName()//oaoafly function getName() { console.log('oaoafly') } 这个区别看似微不足道,但在某些情况下确实是一个难以察觉并且“致命“的陷阱。出现这个陷阱的本质原因体现在这两种类型在函数提升和运行时机(解析时/运行时)上的差异。 第三问
之后Foo函数的返回值是this,而JS的this问题已经有非常多的文章介绍,这里不再多说。 var name = "Wscats";//全局变量 window.name = "Wscats";//全局变量 function getName() { name = "Oaoafly"; //去掉var变成了全局变量 var privateName = "Stacsw"; return function() { console.log(this);//window return privateName } } var getPrivate = getName("Hello"); //当然传参是局部变量,但函数里面我没有接受这个参数 console.log(name) //Oaoafly console.log(getPrivate()) //Stacsw 因为JS没有块级作用域,但是函数是能产生一个作用域的,函数内部不同定义值的方法会直接或者间接影响到全局或者局部变量,函数内部的私有变量可以用闭包获取,函数还真的是第一公民呀~ window.Foo().getName();//- |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|