80%的前端都会做错的一道 JavaScript 面试题,你能做对吗?

347 阅读2分钟

在微信群中看到有人发出了一道 Javascr 面试题,比较菜的我还是很感兴趣的,立马就撸了起来。

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

初步看一下:这道题目涉及的知识点还是挺多的,含有 \color{red}{var、变量提升、作用域、面向对象、运算符优先级} 这几点知识点的考察

第一步:由于 Js 是单线程的,所以代码是一行一行的往下执行的,但是由于变量提升的问题,我们可以得出

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)}

- var getName = function() {console.log(4)}
- function getName() {console.log(5)}
+ getName = function() {console.log(4)}

...省略

变量声明,函数声明会提到最前面来,此时 getName 为 function getName() {console.log(5)}

第二步:看看程序执行到 Foo.getName() 时的变化

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)}

- var getName = function() {console.log(4)}
- function getName() {console.log(5)}
+ getName = function() {console.log(4)}

...省略

此时 getName 为 function getName() {console.log(4)}

第三步:程序执行到 Foo.getName() 结束时,输出结果为 2

第四步:程序执行到 getName() 结束时,输出结果为 4

第五步:程序执行到 Foo().getName() 结束时,输出结果为 1

function Foo() {
  getName = function() {console.log(1)}
  return this
}

...省略
Foo().getName()
...省略

调用了 Foo 函数,因为 Foo 作用域中的 getName 没有用 var 声明,所以 getName 是一个全局变量,即此时的 getName 为 function() {console.log(1)} 又因为 Foo 函数显示的返回 this, Foo() 运行时是一个隐式调用相当于 window.Foo(),所以 this 为 window。 window.getName() => 1

第六步:程序执行到 getName() 结束时,输出结果为 1

第七步:程序执行到 new Foo.getName() 结束时,输出结果为 2

function Foo() {
  getName = function() {console.log(1)}
  return this
}

...省略
new Foo.getName()
...省略

由 Js 运算符优先级可知:. 运算符高于 new ,所以 new Foo.getName() 相当于 new (Foo.getName)()

第八步:程序执行到 new Foo().getName() 结束时,输出结果为 3

new Foo().getName() 相当于 (new Foo()).getName()

第九步:程序执行到 new new Foo().getName() 结束时,输出结果为 3

new new Foo().getName() 相当于 new ((new Foo()).getName)()

Js 原算符优先级汇总表


【学习笔记,有错误之处,敬请指教,谢谢阅读!😊】

【如对您有帮助,请点个赞,谢谢!😊】