zoukankan      html  css  js  c++  java
  • 一道说难不难的js题目

    1、题目

    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);}
    
    //请写出以下输出结果:
    Foo.getName();
    getName();
    Foo().getName();
    getName();
    new Foo.getName();
    new Foo().getName();
    new new Foo().getName();

    答案是:

    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);}
    
    //答案:
    Foo.getName();//2
    getName();//4
    Foo().getName();//1
    getName();//1
    new Foo.getName();//2
    new Foo().getName();//3
    new new Foo().getName();//3
    View Code

    此题涉及的知识点众多,包括变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级等等。

    第一问比较简单,不赘述了。

    第二问

     此处有两个坑,一是声明提前,二是函数表达式。

    声明提前

    即所有声明变量或声明函数都会被提前到当前函数的顶部。

    函数表达式

    var getName和function getName都是声明语句,区别在于var getName是函数表达式,而function getName是函数声明,函数表达式最大的问题,在于js会将此代码拆分为两行代码分别执行。

    上面题目相当于:

    function Foo() {//函数声明
        getName = function () { alert (1); };
        return this;
    }
    var getName;//变量声明提前
    function getName() { alert (5);}//函数声明提前,覆盖变量getName
    Foo.getName = function () { alert (2);};
    Foo.prototype.getName = function () { alert (3);};
    getName = function () { alert (4);};//覆盖变量getName
    
    
    //请写出以下输出结果:
    Foo.getName();
    getName();
    Foo().getName();
    getName();
    new Foo.getName();
    new Foo().getName();
    new new Foo().getName();
    执行到第二问,window.getName被覆盖了两次,输出4。
    
    

    第三问

    先执行了Foo函数,然后调用Foo函数的返回值对象的getName属性函数。
    this的指向问题:

    1.函数在被直接调用的时候,其中的this指针永远指向window

    2.匿名函数this总是指向window对象

    3.谁执行函数,this就指向谁

    4.如果函数new了一下,那么就会创建一个对象,并且this指向新创建的对象

    第三问的this指向window,而window.getName在Foo函数中被第3次覆盖,所以输出1。

    第四问

    
    
    getName即window.getName在第三问中被第3次覆盖,所以输出1。
    
    

    第五问

    此处考察的是js的运算符优先级问题。

    优先级运算类型关联性运算符
    19 圆括号 n/a ( … )
    18 成员访问 从左到右 … . …
    需计算的成员访问 从左到右 … [ … ]
    new (带参数列表) n/a new … ( … )
    17 函数调用 从左到右 … ( … )
    new (无参数列表) 从右到左 new …
    16 后置递增(运算符在后) n/a … ++
    后置递减(运算符在后) n/a … --
    15 逻辑非 从右到左 ! …
    按位非 从右到左 ~ …
    一元加法 从右到左 + …
    一元减法 从右到左 - …
    前置递增 从右到左 ++ …
    前置递减 从右到左 -- …
    typeof 从右到左 typeof …
    void 从右到左 void …
    delete 从右到左 delete …
    14 乘法 从左到右 … * …
    除法 从左到右 … / …
    取模 从左到右 … % …
    13 加法 从左到右 … + …
    减法 从左到右 … - …
    12 按位左移 从左到右 … << …
    按位右移 从左到右 … >> …
    无符号右移 从左到右 … >>> …
    11 小于 从左到右 … < …
    小于等于 从左到右 … <= …
    大于 从左到右 … > …
    大于等于 从左到右 … >= …
    in 从左到右 … in …
    instanceof 从左到右 … instanceof …
    10 等号 从左到右 … == …
    非等号 从左到右 … != …
    全等号 从左到右 … === …
    非全等号 从左到右 … !== …
    9 按位与 从左到右 … & …
    8 按位异或 从左到右 … ^ …
    7 按位或 从左到右 … | …
    6 逻辑与 从左到右 … && …
    5 逻辑或 从左到右 … || …
    4 条件运算符 从右到左 … ? … : …
    3 赋值 从右到左 … = …
    … += …
    … -= …
    … *= …
    … /= …
    … %= …
    … <<= …
    … >>= …
    … >>>= …
    … &= …
    … ^= …
    … |= …
    2 yield 从右到左 yield …
    yield* 从右到左 yield* …
    1 Spread n/a ... …
    0 逗号 从左到右 … , …
    根据上表,得之,(.)优先级高于new,所以这一问相当于:
    new (Foo.getName)();

    第六问

    根据优先级表,得之,new(带参数列表)优先级高于函数调用,所以这一问相当于:
    (new Foo()).getName()

    第七问

    根据优先级表,得之,new(带参数列表)优先级高于函数调用,(.)优先级高于new,函数调用优先级高于new(无参数列表),所以这一问相当于:
    new ((new Foo()).getName)();
    优先级运算类型关联性运算符
    19 圆括号 n/a ( … )
    18 成员访问 从左到右 … . …
    需计算的成员访问 从左到右 … [ … ]
    new (带参数列表) n/a new … ( … )
    17 函数调用 从左到右 … ( … )
    new (无参数列表) 从右到左 new …
    16 后置递增(运算符在后) n/a … ++
    后置递减(运算符在后) n/a … --
    15 逻辑非 从右到左 ! …
    按位非 从右到左 ~ …
    一元加法 从右到左 + …
    一元减法 从右到左 - …
    前置递增 从右到左 ++ …
    前置递减 从右到左 -- …
    typeof 从右到左 typeof …
    void 从右到左 void …
    delete 从右到左 delete …
    14 乘法 从左到右 … * …
    除法 从左到右 … / …
    取模 从左到右 … % …
    13 加法 从左到右 … + …
    减法 从左到右 … - …
    12 按位左移 从左到右 … << …
    按位右移 从左到右 … >> …
    无符号右移 从左到右 … >>> …
    11 小于 从左到右 … < …
    小于等于 从左到右 … <= …
    大于 从左到右 … > …
    大于等于 从左到右 … >= …
    in 从左到右 … in …
    instanceof 从左到右 … instanceof …
    10 等号 从左到右 … == …
    非等号 从左到右 … != …
    全等号 从左到右 … === …
    非全等号 从左到右 … !== …
    9 按位与 从左到右 … & …
    8 按位异或 从左到右 … ^ …
    7 按位或 从左到右 … | …
    6 逻辑与 从左到右 … && …
    5 逻辑或 从左到右 … || …
    4 条件运算符 从右到左 … ? … : …
    3 赋值 从右到左 … = …
    … += …
    … -= …
    … *= …
    … /= …
    … %= …
    … <<= …
    … >>= …
    … >>>= …
    … &= …
    … ^= …
    … |= …
    2 yield 从右到左 yield …
    yield* 从右到左 yield* …
    1 Spread n/a ... …
    0 逗号 从左到右 … , …
  • 相关阅读:
    ecshop 整合 kindedotor
    css 一些小笔记
    linux 使用 随记录
    GIPZ 压缩
    js 代码 随记
    map和list循环遍历
    向数据库批量处理事件
    链表和数组的优劣比较
    内存对齐 和 sizeof小结
    C++的默认构造函数与构造函数
  • 原文地址:https://www.cnblogs.com/MissFelicia/p/5943237.html
Copyright © 2011-2022 走看看