以下面试题是为了考什么????
考基础扎实?
function Foo()
{
getName = function(){return 1;}
return this;
}
Foo.getName=function(){return 2;}
Foo.prototype.getName=function(){return 3;}
var getName=function(){return 4;}
function getName(){return 5;}
//以下内容会输出什么?
console.log(Foo.getName())
console.log(getName());
console.log(Foo().getName());
console.log(getName());
console.log(new Foo.getName());
console.log(new Foo().getName());
console.log(new new Foo().getName());
不符合实际,应试教育的代谢产物
讲真,最后new new那个结果怎么出来的。。。。。
稍微复杂点的插件或者node代码,
还是有用到这些写法和问题的,
并不能说完全没有意义
虽然实际中不可能这么用的,但是这些机制都是js内部基础原理,甚至是某些“坑”,这些又不是C语言那样的未定义行为
,只要了解js的运行机制,这些问题也并不难,深刻理解这些运行机制,在你以后碰到某些坑的时候才不会抓瞎。
Foo.getName()
Foo
构造函数的静态方法,很明显是引用在它本身的方法,输出2
。-
getName()
这里主要是这两句:var getName=function(){return 4;} function getName(){return 5;}
经过声明提升之后会变成这样:
var getName; function getName(){return 5;} getName = function(){return 4;}
所以这里是输出
4
。 Foo().getName()
这里有点麻烦,如果习惯用严格模式的话,就能看出来,这里在严格模式下其实是非法的。因为严格模式禁止this关键字指向全局对象。在非严格模式的情况下,先是运行了Foo()
这个构造函数,由于没有用new
,所以其中的this
指向了windows
,在构造函数内部定义的getName
重新覆盖了原来的全局变量,返回的this
实际上就是window
,所以这里输出的是1
。getName()
经过了第三点,全局变量的getName
已经被改写成Foo()
内部的那个,这里当然仍然输出1
。new Foo.getName()
这里的关键是new
干了啥。规范里写的很长,简述以下就是,首先会创建一个新的空对象,然后把这个新对象的[[Prototype]]
指向后面那个对象的[[Prototype]]
,然后将this
指针指向这个新的空对象,最后会调用后面那个对象下属的[[Construct]]
这个内部方法,对它使用[[call]]
,把this
和括号里面的参数都传进去。
在这里的话,new
后面是Foo.getName
,它是一个函数,那么很明显将调用Function
构造器构造一个函数,所以这里将会返回一个构造函数名字是Foo.getName
的函数(对象)。new Foo().getName()
这里和上面又不一样了,需要这么看(new Foo()).getName()
,先调用Foo()
这个构造函数,实例化一个对象,然后调用这个对象的getName
方法,既然是实例化对象的方法,那当然应当是在原型链上面的,所以这里返回3
。new new Foo().getName()
这里其实就是把5和6结合了起来,先打括号分割一下new (new Foo()).getName()
,同样的先是实例化了一个对象出来,然后再对这个实例化对象的getName
方法使用new
,这个结果和第5是一样的,返回一个构造函数名字是Foo.getName
的函数(对象)。
我倒覺得這個考得還可以。在多人協同的情況下,有這種衝突的情況還是存在的,如果不懂這些先後順序,調代碼就夠受的,知己知彼,百戰不殆。
只针对这个面试题,解答一下
function Foo()
{
getName = function(){return 1;}
return this;
}
Foo.getName=function(){return 2;}
Foo.prototype.getName=function(){return 3;}
var getName=function(){return 4;}
function getName(){return 5;}
//以下内容会输出什么?
console.log(Foo.getName()) //2
console.log(getName()); //4
console.log(Foo().getName()); //1
console.log(getName()); //1
console.log(new Foo.getName()); //{}
console.log(new Foo().getName()); //3
console.log(new new Foo().getName()); //{}
1.第一个返回2应该没疑问;
2.变量声明提升后,return 5那个最先被定义,但后来被return 4的覆盖,因此,返回4;
3.return 1的函数被赋值全局变量getName,Foo()返回window,window.getName()返回1;
4.同上;
5.构造函数return的值如果不是对象会被舍弃,所以返回一个空对象;
6.构造函数Foo()返回的一个空对象{},这个对象是Foo的实例,继承原型上的getName函数,所以返回3;
7.最坑爹的一个,效果应是等同于
console.log(new (new Foo().getName)());
与5同理,返回一个空对象{};
考察你对this
、原型链
、函数对象
、函数声明提前
等一系列知识。
出这样的面试题是希望你能有一个对已有知识的整合能力,当初我在面试的时候也试过被面试官提了一个整合了ajax
请求与事件轮询
相结合的问题,问的是把ajax
请求设为同步请求(async设为false
),然后在其回调函数以及ajax
请求代码的下一行各放一个方法调用,问哪个先执行,当时还不懂事件轮询
的原理直接蒙逼了。
在实战中,更多时候你会接触多方面技术相结合的问题,那么你的思维方式就应该从原来的一元转变成二元或者多元。很典型的就是javascript面向对象设计
,要真正做好这方面的技术,你要把函数对象
、原型链
、闭包
、this
等一系列的知识糅合到一起,才能算是开始起步。
考察函数声明以及名称冲突的解决方式以及对象原型知识。感觉实际用途不多,谁会这么命名呢。