使用'new'创建对象时使用'return'

时间:2012-02-16 01:22:45

标签: javascript node.js

我今天发现了一些非常奇怪的东西:如果使用构造函数和new关键字创建对象,但return是构造函数中的函数,则其行为如下:

  1. 新创建的“对象”是一个函数。
  2. 可以像平常那样调用新函数,但是......
  3. 如果在构造函数中维护对this的引用,this引用从构造函数正确创建的对象。这是您期望从new返回的内容。
  4. 以下是一个例子:

    function Constructor() {
      var self = this;
    
      this.name = 'instance';
      return function() {
        return self;
      }
    }
    

    因此,如果您像这样实例化它:var instance = new Constructor() 结果如下:

    typeof instance    //returns "function"
    typeof instance()  //returns "object"
    instance()         //returns { name: 'instance' }
    

    所以我猜我有三个问题:

    1. 这是合法的,是否可以跨浏览器工作?它真的很棒,我认为它可以在很多方面使用,但这种行为是否可靠?
    2. 导致此行为的后台会发生什么?
    3. (可能由2回答,但是......)新实例中是否有新对象(以'this'引用的对象),所以它都是自包含的并且被垃圾收集器正确清理了? / LI>

3 个答案:

答案 0 :(得分:7)

  1. 是的,虽然构造函数默认返回正在构造的新对象(由this引用),但您可以覆盖该返回值,只要你返回一个对象。因为函数是一个对象,所以您可以像在示例中一样返回它。新创建的对象函数本身,但返回的函数在其变量范围内引用新创建的对象。

  2. 参见#1

  3. 这是因为函数创建了一个闭包,因此它继续引用self变量,该变量恰好引用了正在构造的实际对象。所以我不会说它是“内部”任何东西,而只是函数变量范围的一部分。

  4. 要理解的是,您的功能与任何其他功能没有任何不同。就像你已经返回一个数组一样,你只需要一个可以引用新对象的常规数组。

    function Constructor() {
    
      this.name = 'instance';
      return [ this ];  // Instead return an Array that references the new object
    }
    

答案 1 :(得分:2)

嗯,这是一个非常好的问题,正如你可能已经猜到的那样,不容易回答。

简单地说:
1)是和是;这是“传统”编程语言中没有的令人惊叹的功能之一 2)请阅读关闭(下面的链接)
3)是(请阅读更多)

您应该阅读有关Javascript Closures的更多信息: http://jibbering.com/faq/notes/closures/
http://www.javascriptkit.com/javatutors/closures.shtml(这里有一些很好的工作示例)

,更具体地说,寄生遗传模型:
http://blog.higher-order.net/2008/02/21/javascript-parasitic-inheritance-power-constructors-and-instanceof/

我希望这会有所帮助

答案 2 :(得分:1)

这就是你所说的closure

它的作用是创建一个独立的代码环境(通常称为对象)

typeof instance    //returns "function" - since it's not "fired" or called. just returns the function declaration (correct me if i'm wrong)
typeof instance()  //returns "object" - it returns an object since you called it
instance()         //returns an object also - you called it, but you didn't store it

使用闭包构建的对象的示例:

function Constructor() {
    var privateProperty = 'private';
    var privateMethod = function(){
        alert('called from public method');
    };

    //return only what's to be seen in public
    return {
        publicProperty: 'im public',
        publicMethod: function(){
            alert('called from public method');
        }
        getter: privateMethod //assign to call the private method
    }
}

var myObj = Constructor();
var pubProp = myObj.publicProperty; // pubProp = 'im public'
myObj.publicMethod()                //alert: 'called from public method';
myObj.getter()                      //alert: 'called from public method';

//cannot access since "private":
myObj.privateProperty
myObj.privateMethod