Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

下面这段代码的输出是什么? #24

Open
YvetteLau opened this issue Apr 21, 2019 · 3 comments
Open

下面这段代码的输出是什么? #24

YvetteLau opened this issue Apr 21, 2019 · 3 comments

Comments

@YvetteLau
Copy link
Owner

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();
@YvetteLau
Copy link
Owner Author

**说明:**一道经典的面试题,仅是为了帮助大家回顾一下知识点,加深理解,真实工作中,是不可能这样写代码的,否则,肯定会被打死的。

1.首先预编译阶段,变量声明与函数声明提升至其对应作用域的最顶端。

因此上面的代码编译后如下(函数声明的优先级先于变量声明):

function Foo() {
    getName = function() {console.log(1)};
    return this;
}
var getName;
function getName() {console.log(5)};
Foo.getName = function() {console.log(2)};
Foo.prototype.getName = function() {console.log(3)};
getName = function() {console.log(4)};

2.Foo.getName();直接调用Foo上getName方法,输出2

3.getName();输出4,getName被重新赋值了

4.Foo().getName();执行Foo(),window的getName被重新赋值,返回this;浏览器环境中,非严格模式,this 指向 window,this.getName();输出为1.

如果是严格模式,this 指向 undefined,此处会抛出错误。

如果是node环境中,this 指向 global,node的全局变量并不挂在global上,因为global.getName对应的是undefined,不是一个function,会抛出错误。

5.getName();已经抛错的自然走不动这一步了;继续浏览器非严格模式;window.getName被重新赋过值,此时再调用,输出的是1

6.new Foo.getName();考察运算符优先级的知识,new 无参数列表,对应的优先级是18;成员访问操作符 . , 对应的优先级是 19。因此相当于是 new (Foo.getName)();new操作符会执行构造函数中的方法,因此此处输出为 2.

7.new Foo().getName();new 带参数列表,对应的优先级是19,和成员访问操作符.优先级相同。同级运算符,按照从左到右的顺序依次计算。new Foo()先初始化 Foo 的实例化对象,实例上没有getName方法,因此需要原型上去找,即找到了 Foo.prototype.getName,输出3

8.new new Foo().getName(); new 带参数列表,优先级19,因此相当于是 new (new Foo()).getName();先初始化 Foo 的实例化对象,然后将其原型上的 getName 函数作为构造函数再次 new ,输出3

因此最终结果如下:

Foo.getName(); //2
getName();//4
Foo().getName();//1
getName();//1
new Foo.getName();//2
new Foo().getName();//3
new new Foo().getName();//3

@moruifei
Copy link

小姐姐对知识点的理解真透彻 很强~

@jungre19
Copy link

jungre19 commented Mar 4, 2021

小姐姐厉害,看了很多你的文章,很有帮助

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants