这段代码很有意思!

2021-08-16 15:52:42 浏览数 (1)

这段代码很有意思!

当你看到这段代码时,你的心情是怎样的呢!

这是几个同学给我的答复,嗯,就很好

能不能搞点阳间的代码 !

指定有什么大病

哪个人才写出这样的代码

代码语言: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两块代码来讲

代码语言:javascript复制
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

代码语言:javascript复制
function Foo() {
    getName = function() {
        console.log(1);
    }
    return this
}

第四个

getName()输出1

因为在执行上一个函数时,由于getName是定义在全局的,所以在执行时,实际上改变了全局作用域下的getName的值,所以再次执行getName(),输出的是1

代码语言:javascript复制
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关键字

  1. 创建一个空对象
  2. 空对象的继承构造函数的原型
  3. 让this指向构造函数的对象实例,执行构造函数内容为新对象添加属性和方法
  4. 返回this
代码语言:javascript复制
Foo.prototype.getName = function() {
    console.log(3);
}

第七个

终于到最后一个了

new new Foo().getName()输出 3

相当于执行new (new Foo().getName())先执行括号里的,也就是上一题的,也就是输出3


终于!!

其实写完感觉也不是很难,思路清晰,不要乱套还是可以拿下的,希望大家在碰到这种阴间代码时,能够把它妥妥拿下!!

0 人点赞