一道面试题 包含了new的细节 和运算符的优先级 还有属性访问机制
function foo() {
getname = function () { alert(1); } return this; }
foo.getname = function () { alert(2); } foo.prototype.getname = function () { alert(3); } var getname = function () { alert(4); } function getname () { alert(5); }
这是在网上看到的一道面试题 嗯 考察的知识点挺多 其他的就不多说了
我用我的理解与解题方式来解答这道题
1.首先是变量提升
变量提升包括var 声明的变量和fucntion 声明
举个例子
1.var a=4;
2.function test(){
console.log(456);
};
函数变量声明会先于普通变量之前,并且不会被后面的同名覆盖
但是会被后面的同名赋值覆盖!
就是 function a(){};
var a;
这样不会覆盖函数a
但是如果 var a=4;
函数a就会被覆盖
接下来从第一个开始分析
foo.getname();
首先变量提升之后是这个样子滴
//变量提升
第一题function foo(){
getname = function () { alert(1); }//foo函数执行的时候 会覆盖全局中的getname
return this;
/*
new 运算符的时候会执行以下
var obj={};//创建一个空对象
将构造函数的作用域赋给新对象
这个新对象的内置原形指向构造函数的原形对象
obj.__proto__=foo.prototype;
执行构造函数中的代码
返回这个对象(如果显示返回基本数据类型 无效 还是会返回这个对象
如果返回的是引用类型 那么这个对象将没用了)
*/
}
//变量提升
//2.function getname () { alert(5); }
//变量提升
3.var getname;
4.foo.getname = function () { alert(2); }
5.foo.prototype.getname = function () { alert(3); }
6.getname = function () { alert(4); }
之前的2 会被6覆盖 所以2就可以注释掉了
第二题 foo.getname(); //弹出窗口值为2 不用解释了吧
第三题 getname();//弹出窗口值为4
第四题 foo().getname();
先执行foo();
里面的getname=function(){alert(1);} 会覆盖全局作用域中的6
因为是在全局作用域下调用foo函数 所以this就是window
window.getname(); //弹出窗口值为6
第五题 new foo.getname();
new (foo.getname)(); //弹出窗口值为2
笨想:肯定不会是执行foo.getname 之后才new 会报错
优先级问题 .(成员访问的优先级高于new 并且从左到右
于是就把foo.getname这个函数当做构造函数执行
第六题
new foo().getname();
.运算符从左到右
new foo(); 返回一个foo类型的对象 {}
{}.getname();
找不到 然后去构造它的函数foo的prototype上找
foo.prototype.getname = function () { alert(3); }
所以结果 3
第七题
也是运算符优先级的问 new new foo().getname(); 在这里面.的优先级最高
new ((new foo()).getname)();
先执行.左 然后.右
先执行foo(); 然后new 返回一个foo类型的对象
然后得到getname的函数体
然后当做构造函数执行 alert(3) 然后返回一个foo.getname类型的对象
可能有些地方不是让所有人懂
毕竟我也是一直菜鸟
// foo.getname(); //2 // getname(); //4 // foo().getname(); //1 // getname(); //1 // new foo.getname();//2 // new foo().getname();//3 // new (new foo().getname)()//3;
优先级 |
运算类型 |
关联性 |
运算符 |
20 |
n/a |
( … ) |
|
19 |
从左到右 |
… . … |
|
从左到右 |
… [ … ] |
||
new (带参数列表) |
n/a |
new … ( … ) |
|
从左到右 |
… ( … ) |
||
18 |
new (无参数列表) |
从右到左 |
new … |
17 |
后置递增(运算符在后) |
n/a |
… ++ |
后置递减(运算符在后) |
n/a |
… -- |
|
16 |
从右到左 |
! … |
|
从右到左 |
~ … |
||
从右到左 |
+ … |
||
从右到左 |
- … |
||
从右到左 |
++ … |
||
从右到左 |
-- … |
||
从右到左 |
typeof … |
||
从右到左 |
void … |
||
从右到左 |
delete … |
||
15 |
从右到左 |
… ** … |
|
14 |
从左到右 |
… * … |
|
从左到右 |
… / … |
||
从左到右 |
… % … |
||
13 |
从左到右 |
… + … |
|
从左到右 |
… - … |
||
12 |
从左到右 |
… << … |
|
从左到右 |
… >> … |
||
从左到右 |
… >>> … |
||
11 |
从左到右 |
… < … |
|
从左到右 |
… <= … |
||
从左到右 |
… > … |
||
从左到右 |
… >= … |
||
从左到右 |
… in … |
||
从左到右 |
… instanceof … |
||
10 |
从左到右 |
… == … |
|
从左到右 |
… != … |
||
从左到右 |
… === … |
||
从左到右 |
… !== … |
||
9 |
从左到右 |
… & … |
|
8 |
从左到右 |
… ^ … |
|
7 |
从左到右 |
… | … |
|
6 |
从左到右 |
… && … |
|
5 |
从左到右 |
… || … |
|
4 |
从右到左 |
… ? … : … |
|
3 |
从右到左 |
… = … |
|
… += … |
|||
… -= … |
|||
… *= … |
|||
… /= … |
|||
… %= … |
|||
… <<= … |
|||
… >>= … |
|||
… >>>= … |
|||
… &= … |
|||
… ^= … |
|||
… |= … |
|||
2 |
从右到左 |
yield … |
|
从右到左 |
yield* … |
||
1 |
n/a |
... … |
|
0 |
从左到右 |
… , … |
上一篇: react与fetch
下一篇: Ajax乱码问题整理