经典面试题 Foo().getName() 解析
题目如下,写出输出内容(注释:abcde为步骤标号,便于下边分析定位)
// 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();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
解析:
1. Foo.getName(); // 2
Foo为一个函数对象,对象都可以有属性,题目 b 处定义Foo的getName属性为函数,输出2
2. getName(); // 4
这里看d、e处,d为函数表达式,e为函数声明,两者区别在于变量提升,这两处可以等价于
var getName = undefined;
// e处提升到顶部
getName = function () {
console.log(5);
}...
// d. 重新赋值
getName = function () {
console.log(4);
}
// e....
可见函数声明的 5 会被后边函数表达式的 4 覆盖。
3. Foo().getName(); // 1
这里要看a处,在Foo内部将全局的getName重新赋值为 console.log(1) 的函数,执行Foo()返回 this,这个this指向window,Foo().getName() 即为window.getName(),输出 1。
4. getName(); //1
上述3中,全局的getName已经被重新赋值,所以这里依然输出 1。
5. new Foo.getName(); // 2
这里等价于 new (Foo.getName()),先执行 Foo.getName(),输出 2,然后new一个实例;
6. new Foo().getName(); // 3
【前端面试|new new Foo().getName()面试题解析】这里等价于 (new Foo()).getName(), 先new一个Foo的实例,再执行这个实例的getName方法,但是这个实例本身没有这个方法,所以去原型链__protot__上边找,实例.__protot__ === Foo.prototype,所以输出 3。
7. new new Foo().getName(); // 3
这里等价于new (new Foo().getName()),如上述6,先输出 3,然后new 一个 new Foo().getName() 的实例。
补充:
关于上述 5中 new Foo.getName()先执行 Foo.getName(),而6中 new Foo().getName() 先执行 new Foo(),是因为:
- new Foo() 属于new(带参数列表)
- new Foo属于new(无参数列表)
带参数列表的优先级为19,而成员访问的优先级也为19,按照运算符规则(同一优先级,按照从左向右的执行顺序),new Foo().getName()先执行new Foo(),再对new之后的实例进行成员访问.getName()操作。
这是js运算符的优先级链接,可查看每个运算符的优先级。
推荐阅读
- 操作系统|[译]从内部了解现代浏览器(1)
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- 接口|axios接口报错-参数类型错误解决
- JavaScript|vue 基于axios封装request接口请求——request.js文件
- vue.js|vue中使用axios封装成request使用
- JavaScript|JavaScript: BOM对象 和 DOM 对象的增删改查
- JavaScript|JavaScript — 初识数组、数组字面量和方法、forEach、数组的遍历
- JavaScript|JavaScript — call()和apply()、Date对象、Math、包装类、字符串的方法
- JavaScript|JavaScript之DOM增删改查(重点)
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export