一道Javascript笔试题

看不到输入框和运行按钮的童鞋请直接点击标题查看原文。

Tips:You can change the code before run.

运行一下,发现结果是True的。这是为什么呢?

首先我们先确定 return C(); 在这里构成一个闭包,即返回了对C方法的引用,F()有返回值,所以这里new不能当做创建一个F对象来理解,我们先调试一下,看看这里怎么把 this 给弄走了。

Tips:You can change the code before run.

第一个alert出来的结果是F本身,第二个的结果则已经改变了。

那么我们可以先确定,return C()之后,方法C再也不是作为F的任何成员来运行了。 new 操作符作用在F上之后,返回的C方法中 this 指针不再指向F的任何实例化对象了。

这里的难点在于,这个 new 到底干了些什么事情,让 this 与其分道扬镳了呢?

这篇文章讨论的new function中有一句话:

只要 new 表达式之后的 constructor 返回(return)一个引用对象(数组,对象,函数等),都将覆盖new创建的匿名对象,如果返回(return)一个原始类型(无 return 时其实为 return 原始类型 undefined),那么就返回 new 创建的匿名对象。

我们这里的返回的是对C方法的一个引用(函数本身也是对象),由于闭包的关系,C方法并没有在创建完对象之后被GC释放掉,而是直接覆盖了 new 表达式创建的匿名对象,而我们已经将此时的C方法赋值给了某一个全局变量,即:C方法此时已经是全局变量 window 的一个方法了。

那么其中的 this 指针,理所当然就是指向 window 了。

作为对照,我们改动一下代码:

Tips:You can change the code before run.

这个例子就比较好理解了,F()方法没有 new 来干扰,直接作为全局 window 的一个方法运行,所以结果仍然是 b == window 的。

此题其实跟闭包没啥关系,我一看到返回函数的就以为是闭包,结果就直接说闭包我不熟悉……闭包还要返回的函数外有参数被返回的函数使用,这才构成闭包呢。

此题的关键在于:new function、引用对象、闭包、以及Javascript中任何东西都是对象(对象意味着引用)的理解上。

本文来自: http://yyfrankyy.com/blog/671

6 条评论

  1. meteoric_cryNo Gravatar says:

    function F(){
    return new function() {
    this.abc = “abc”;
    return this;
    }
    }
    F.abc = ‘123′
    var a = new F();
    alert(a == window);
    alert(a.abc)

  2. frankNo Gravatar says:

    @meteoric_cry 这个同样道理,有点变化~new F()的结果被new function替代掉了,但也不是window,因为里面的new function已经是返回一个匿名对象,而不是像上面例子一样返回一个方法……

  3. 草依山No Gravatar says:

    不错
    最精要的两句是:
    1.只要 new 表达式之后的 constructor 返回(return)一个引用对象(数组,对象,函数等),都将覆盖new创建的匿名对象,如果返回(return)一个原始类型(无 return 时其实为 return 原始类型 undefined),那么就返回 new 创建的匿名对象。

    2.C方法是window对象的一个方法

  4. zzNo Gravatar says:

    这个题的考点有两点:
    1.就是你说的new的语法,当return值不是一个对象时才返回新生成的对象
    2.C()方法的调用问题,当C不是某个对象的属性时,在调用C时,this指向的是global object,此处就是window

  5. George WingNo Gravatar says:

    本人在想:构造函数类中的this与函数(闭包)中的this的指向有什么不同。

  6. George WingNo Gravatar says:

    本人在想:构造函数类中的this与函数(作用域链)中的this的指向有什么不同。

留言