一道经典的面试题,下面用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;
}
//b
Foo.getName = function() {
console.log(2);
};
//c
Foo.prototype.getName = function() {
console.log(3);
};
//d
var getName = function() {
console.log(4);
};
//e
function getName() {
console.log(5);
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3
new 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 getName
getName = 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