这段代码很有意思!
当你看到这段代码时,你的心情是怎样的呢!
这是几个同学给我的答复,嗯,就很好
代码语言:javascript复制能不能搞点阳间的代码 !
指定有什么大病
哪个人才写出这样的代码
//第一块
function Foo() {
getName = function() {
console.log(1);
}
return this
}
//第二块
Foo.getName = function() {
console.log(2);
}
//第三块
Foo.prototype.getName = function() {
console.log(3);
}
//第四块
var getName = function() {
console.log(4);
}
//第五块
function getName() {
console.log(5);
}
//写出以下各式的输出结果
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
作为菜鸟的我,在面试的时候,看到了这阴间代码,心里想着谁无聊写这样的代码呀,屁点用没有,却只能默默的分析题目,但最终还是错了几个,回来之后又好好分析了一下,其实也不是很难,只是在面试的时候看到这样的东西,实在是有点搞心态了!
大家可以先自己尝试写一下这道题
下面我们来一个一个的分析它
一下是本菜鸟的小题解,有什么错误的地方欢迎大家指出,共同进步!!!!
第一个
Foo.getName()
输出2
第一个并不难,主要和一二,两块代码有关
代码语言:javascript复制function Foo() {
getName = function() {
console.log(1);
}
return this
}
Foo.getName = function() {
console.log(2);
}
其实这前面的只是一个迷惑作用,给函数直接添加属性和方法,实际上是可以的,因为函数也是对象,但是和数组一样,不会改变原先属性的值,也就是Foo.getName
是给Foo
对象下添加一个属性,值是一个函数,和Foo
函数下的getName
是不影响的,所以Foo.getName()
实际上是访问Foo
对象下的getName
输出2
第二个
getName()
输出4
这个考察的是预编译的知识,直接执行了getName
,这里就摘取4,5两块代码来讲
var getName = function() {
console.log(4);
}
function getName() {
console.log(5);
}
在预编译的过程中会经历以下几步
代码语言:javascript复制第一步:创建一个Go对象,因为这里是在全局下
Go {}
第二步:找形参和变量声明,值给undefined
Go {
getName:undefined;
}
第三步:实参形参统一,这里没有形参
Go {
getName:undefined
}
第四步:找函数声明,值赋予函数体
Go {
getName:getName();
}
当预编译执行完成后,才开始执行代码,也就是那条函数表达式,getName
被赋予了新的函数体,也就是输出4
第三个
Foo().getName()
输出1
Foo()
先执行,全局下的getName
被重新赋值,返回了一个this
,这里的this
指向的是window,此时的getName
实际上是window.getName
也就是输出1
function Foo() {
getName = function() {
console.log(1);
}
return this
}
第四个
getName()
输出1
因为在执行上一个函数时,由于getName
是定义在全局的,所以在执行时,实际上改变了全局作用域下的getName
的值,所以再次执行getName()
,输出的是1
function Foo() {
getName = function() {//在执行上一条语句时,改变了全局变量的值
console.log(1);
}
return this
}
//这里声明了变量getName,为全局变量
var getName = function() {
console.log(4);
}
第五个
new Foo.getName()
输出
在做这道题之前需要知道,运算符的优先级,这是从MDN文档上的截图,可以看到成员访问运算符的优先级大于new
一个无参列表的有限级,也就是new Foo.getName()
实际上是new (Foo.getName())
,括号内输出2
new Foo
属于new无参数列表
第六个
new Foo().getName()
输出 3
相当于执行(new Foo()).getName()
new Foo()
实例化了Foo
这个构造函数,返回的是继承有Foo()
原型的新对象,在执行getName()
时,由于新对象下没有这个方法,会沿着原型链上寻找,能够在原型上找到并输出3
new关键字
- 创建一个空对象
- 空对象的继承构造函数的原型
- 让this指向构造函数的对象实例,执行构造函数内容为新对象添加属性和方法
- 返回this
Foo.prototype.getName = function() {
console.log(3);
}
第七个
终于到最后一个了
new new Foo().getName()
输出 3
相当于执行new (new Foo().getName())
先执行括号里的,也就是上一题的,也就是输出3
终于!!
其实写完感觉也不是很难,思路清晰,不要乱套还是可以拿下的,希望大家在碰到这种阴间代码时,能够把它妥妥拿下!!