【问题标题】:Is there any reason to manually `return` in a constructor function?是否有任何理由在构造函数中手动“返回”?
【发布时间】:2012-11-21 01:10:17
【问题描述】:

通常,在构造函数中,绑定到函数内this 的对象在使用new 前缀调用时由它返回。但我想也有可能(我想我什至在 crockford 的书中读过这个)手动返回你自己的值。有没有这样的做法有用的地方?

【问题讨论】:

  • 如果它是一个对象,你只能返回你自己的值。

标签: javascript oop compiler-construction return new-operator


【解决方案1】:

如果您从构造函数返回值类型,您将获得不同的行为,具体取决于是否使用了new。这就是String 的工作原理。在你的 JavaScript 控制台中查看这个对象:

{
    s: String("abc"),
    S: new String("abc")
}

s 包含一个字符串值,但大S 包含一个字符串对象。也许是细微的差别。

您可以超越这一点,将相同的功能用于不同的目的:

function Foo() {
    return "abc";
}
Foo.prototype.DoSomething = function () {
    // something completely unrelated to "abc"
};
var a = Foo();      // The string "abc".  Does not have a DoSomething() method.
var b = new Foo();  // An Object with a DoSomething() method.  Doesn't know about "abc".

取决于是否使用了new,你会得到完全不同的东西。

【讨论】:

    【解决方案2】:

    如果您想实现单例模式,则可以使用此模式,方法是确保在第一次构造对象后不再构造另一个对象 - 而是返回第一个构造的对象。

    if(!TheClass.singleton) TheClass.singleton = this;
    return TheClass.singleton
    

    【讨论】:

    • 不是真的:问题是关于使用带有 new 关键字的构造函数。如果这段代码在构造函数Foo 中,唯一的效果是TheClass.singleton 将等于使用new Foo() 创建的第一个实例。但是,您的代码暗示随后调用 var foo2 = new Foo() 将返回单例,这绝对不是真的。
    • 嗯。如果这绝对不是真的,那么问题的整个前提不是不正确的吗?还是我的代码有错误?
    • @meetamit:测试一下。虽然我认为if(!TheClass.singleton) 是有意的。
    • 是的,我在很大程度上得到了纠正(我也尝试过:jsfiddle.net/JWYeg/1)。很抱歉使用了“肯定”这个词。不过,这在很大程度上扰乱了我的世界。多年来,我一直生活在这样的印象中,那就是这永远行不通。是否有旧版本的 JavaScript 不是这种情况?
    • @meetamit 如果你有兴趣,我在这里发布了一个关于版本的问题:stackoverflow.com/questions/13485455/…
    【解决方案3】:

    构造函数(即用new 调用的函数)总是返回一个对象,this 是默认值。在某些情况下,您可能会使用说:

    function Foo(arg) {
      if ( !(this instanceof Foo) ) {
        return new Foo(arg);
      }
      this.blah = arg;
    }
    

    所以你返回一个不同的对象到函数的this,但它仍然返回一个自身的实例。

    【讨论】:

    • 如果Foo 的原型包含Foo,这可能会失败,因为那时this 将引用一个已经存在的Foo 对象,但我不确定会有什么原因是为了首先设置这种情况......
    • 实际上,我刚刚意识到这可能是一个非常理想的结果——它本质上使调用someFoo.Foo(arg) 成为对象的重新初始化,这是一个非常简洁的代码重用工具...
    • 很酷的 hack,我相信 crockford 会同意的,但任何阅读本文的人都应该查看 this 答案。
    • @Jeff——说This might fail if the prototype of Foo contained Foo 没有意义,除非您的意思是如果Foo 被调用为实例的方法(即foo.Foo())。我不使用这种方法,如果在应该调用构造函数时没有使用new 调用,则代码应该无法通过测试。这只是返回其他对象的原因的一个示例。
    • 我知道,我指出的正是这种情况 (foo.Foo())。这不是对该方法的批评,只是对使用此技术的任何人的说明,即在没有new 关键字的情况下调用该方法的情况可能会出现意外行为。
    【解决方案4】:

    是的,这样想。

    item = function(id){
      if(alreadytaken(id)){
        return cache[id];
      }else{
        cache[id] = this;
      }
    }
    
    var newitem = new item(1);
    var newitem2 = new item(1);
    

    此示例检查 ID 以查看它是否已存在。如果确实如此,那么它将强制返回已经存在的对象,这是我过去实际使用过的对象。

    【讨论】:

    • 如果你暗示newitem == newitem2 那绝对不是真的。您的代码的唯一特殊结果是 cache[1] 将等于 newitem 而不是 newitem2
    • 这个答案很混乱,你还不如return;。返回cache[id] 不会返回任何内容,它只是停止执行,只要您在调用时使用new 关键字。
    • @David:他们为什么不一样?如果已使用该 ID 创建了对象,则返回缓存的对象。 (假设 alreadytaken 检查缓存中的那个 ID)。 所以是的,它们是相等的。
    • @user1689607 使用 new 关键字时,您不能“强制返回”任何内容。作为回报,您将始终获得新创建的对象。
    • @David:这是不正确的。整个问题的前提是您可以在使用new 调用时覆盖返回值。 jsfiddle.net/UVsbK
    猜你喜欢
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多