一道经典的面试题,下面用a b c d 标注方便讲解
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>//a function Foo() {getName = function() {console.log(1);};return this;}//bFoo.getName = function() {console.log(2);};//cFoo.prototype.getName = function() {console.log(3);};//d var getName = function() {console.log(4);};//e function getName() {console.log(5);}Foo.getName(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1new Foo.getName(); // 2new Foo().getName(); // 3new new Foo().getName(); // 3</script>
</body></html>
解析:
1. Foo.getName(); // 2
对象.属性 这里Foo作为函数对象,getName()作为Foo的函数属性,所以看题目b处
2.getName(); // 4
这里主要看题目d e 处,d处为一个函数表达式,e声明了一个函数
两者内容相同,我们可以根据函数优先规则 函数声明>变量
那e处提到题目前面
根据js自上而下运行,先运行题目e处,再把d处赋值给getName,所以覆盖了e处
如下
//e 声明了一个getName函数let getNamegetName = function() {console.log(5);}//d 函数表达式getName = function() {console.log(4);};
?
3.Foo().getName(); // 1**
? 这里看题目a处
? 因为Foo打了小括号,所以就是调用Foo函数
? 并且给全局变量getName重新赋值
4.getName(); // 1
? 因为前面3运行题目a处,给getName赋值了
5. new Foo.getName(); // 2
? 对象.属性,这里看b处
? new Foo.getName==new(Foo.getName())
? 所以这里先调用了Foo.getName,运行结果为2
? 然后再实例化返回值2
6.new Foo().getName(); // 3
? 因为Foo打了小括号,所以就是调用Foo函数
? 并且前面有new,就意味着是用new调用的Foo函数
? 那么此时相当于是把Foo当做了构造函数
? 相当于(new Foo()).getName()
? 所以返回了Foo实例化出来的对象,这个对象自己没有
? getName方法,所以就访问原型里的getName,既题目c处
7.new new Foo().getName(); // 3
? 这里可以看做new((new Foo()).getName())
? 右上可得 new(3)
? 所有实例化返回值为3
写在最后,都是个人理解,题目讲解方式参照博客大佬排版
https://blog.csdn.net/redatao/article/details/107955687