我是一条有梦想的咸鱼

一道面试题 包含了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

从右到左

typeof …

void

从右到左

void …

delete

从右到左

delete …

15

从右到左

… ** …

14

乘法

从左到右

… * …

除法

从左到右

… / …

取模

从左到右

… % …

13

加法

从左到右

… + …

减法

从左到右

… - …

12

按位左移

从左到右

… << …

按位右移

从左到右

… >> …

无符号右移

从左到右

… >>> …

11

小于

从左到右

… < …

小于等于

从左到右

… <= …

大于

从左到右

… > …

大于等于

从左到右

… >= …

in

从左到右

… in …

instanceof

从左到右

… instanceof …

10

等号

从左到右

… == …

非等号

从左到右

… != …

全等号

从左到右

… === …

非全等号

从左到右

… !== …

9

按位与

从左到右

… & …

8

按位异或

从左到右

… ^ …

7

按位或

从左到右

… | …

6

逻辑与

从左到右

… && …

5

逻辑或

从左到右

… || …

4

条件运算符

从右到左

… ? … : …

3

赋值

从右到左

… = …

… += …

… -= …

… *= …

… /= …

… %= …

… <<= …

… >>= …

… >>>= …

… &= …

… ^= …

… |= …

2

yield

从右到左

yield …

yield*

从右到左

yield* …

1

展开运算符

n/a

... …

0

逗号

从左到右

… , …

posted @ 2018-09-22 12:38  帅哥天下9  阅读(1029)  评论(0编辑  收藏  举报