H5W3
当前位置:H5W3 > JavaScript > 正文

【JS】求出此面试题的人员的心态!

以下面试题是为了考什么????
考基础扎实?

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());

考察你对this原型链函数对象函数声明提前等一系列知识。

出这样的面试题是希望你能有一个对已有知识的整合能力,当初我在面试的时候也试过被面试官提了一个整合了ajax请求与事件轮询相结合的问题,问的是把ajax请求设为同步请求(async设为false),然后在其回调函数以及ajax请求代码的下一行各放一个方法调用,问哪个先执行,当时还不懂事件轮询的原理直接蒙逼了。

在实战中,更多时候你会接触多方面技术相结合的问题,那么你的思维方式就应该从原来的一元转变成二元或者多元。很典型的就是javascript面向对象设计,要真正做好这方面的技术,你要把函数对象原型链闭包this等一系列的知识糅合到一起,才能算是开始起步。

只针对这个面试题,解答一下

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同理,返回一个空对象{};

虽然实际中不可能这么用的,但是这些机制都是js内部基础原理,甚至是某些“坑”,这些又不是C语言那样的未定义行为,只要了解js的运行机制,这些问题也并不难,深刻理解这些运行机制,在你以后碰到某些坑的时候才不会抓瞎。

  1. Foo.getName()
    Foo构造函数的静态方法,很明显是引用在它本身的方法,输出2

  2. getName()
    这里主要是这两句:

    var getName=function(){return 4;}
    function getName(){return 5;}

    经过声明提升之后会变成这样:

    var getName;
    function getName(){return 5;}
    getName = function(){return 4;}

    所以这里是输出4

  3. Foo().getName()
      这里有点麻烦,如果习惯用严格模式的话,就能看出来,这里在严格模式下其实是非法的。因为严格模式禁止this关键字指向全局对象。在非严格模式的情况下,先是运行了Foo()这个构造函数,由于没有用new,所以其中的this指向了windows,在构造函数内部定义的getName重新覆盖了原来的全局变量,返回的this实际上就是window,所以这里输出的是1

  4. getName()
    经过了第三点,全局变量的getName已经被改写成Foo()内部的那个,这里当然仍然输出1

  5. new Foo.getName()
      这里的关键是new干了啥。规范里写的很长,简述以下就是,首先会创建一个新的空对象,然后把这个新对象的[[Prototype]]指向后面那个对象的[[Prototype]],然后将this指针指向这个新的空对象,最后会调用后面那个对象下属的[[Construct]]这个内部方法,对它使用[[call]],把this和括号里面的参数都传进去。
      在这里的话,new后面是Foo.getName,它是一个函数,那么很明显将调用Function构造器构造一个函数,所以这里将会返回一个构造函数名字是Foo.getName的函数(对象)。

  6. new Foo().getName()
      这里和上面又不一样了,需要这么看(new Foo()).getName(),先调用Foo()这个构造函数,实例化一个对象,然后调用这个对象的getName方法,既然是实例化对象的方法,那当然应当是在原型链上面的,所以这里返回3

  7. new new Foo().getName()
      这里其实就是把5和6结合了起来,先打括号分割一下new (new Foo()).getName(),同样的先是实例化了一个对象出来,然后再对这个实例化对象的getName方法使用new,这个结果和第5是一样的,返回一个构造函数名字是Foo.getName的函数(对象)。

讲真,最后new new那个结果怎么出来的。。。。。

考察函数声明以及名称冲突的解决方式以及对象原型知识。感觉实际用途不多,谁会这么命名呢。

不符合实际,应试教育的代谢产物

我倒覺得這個考得還可以。在多人協同的情況下,有這種衝突的情況還是存在的,如果不懂這些先後順序,調代碼就夠受的,知己知彼,百戰不殆。

稍微复杂点的插件或者node代码,
还是有用到这些写法和问题的,
并不能说完全没有意义

讲解的很详细的http://www.cnblogs.com/xxcang

回答

本文地址:H5W3 » 【JS】求出此面试题的人员的心态!

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址