【问题标题】:Calling Javascript Factory Method调用 Javascript 工厂方法
【发布时间】:2012-01-03 03:21:08
【问题描述】:

我正在学习面向对象的 Java 脚本。我有以下工厂方法的代码。

function Foo() {
    var value = 1;
    return {
        method: function() {
            return value;
        },
        value:value
    }
}
Foo.prototype = {
    bar: function() {}
};

new Foo();
Foo();

方法 Foo 可以通过两种方式调用。 new Foo();Foo(); 两者都做同样的事情并且输出是相同的。 java脚本处理的实际区别是什么?

【问题讨论】:

  • 请注意,如果您要从 Foo() 函数返回您自己的对象,而不是使用 JS 为您创建的对象,当您说 new Foo() 时,设置 Foo.prototype = {something} 是没有意义的。
  • @Bakudan - 从任何合理的术语定义来看,JavaScript 都是面向对象的。
  • @Bakudan,如果您有话要说(面向对象与基于对象),请在新答案中用示例证明它的合理性。它将帮助新手:)
  • @onemach,你可以贡献答案,而不是拼写错误:)
  • 可能不值得自己回答,但请注意new Foo 不会有属性bar。使用new时,如果不返回对象,则返回Foo.prototype。由于您在每次调用中都创建了一个对象字面量,因此它会被返回。

标签: javascript


【解决方案1】:

在正常情况下,new 应在从构造函数创建对象时使用,而在执行任何其他函数调用时应避免使用。在函数上使用new 时 1) 创建了一个新对象; 2) 使用绑定到该新对象的 this 的值调用函数,并且 3) 从函数返回的值(默认情况下)是在第一步中创建的对象。

但是,在您的情况下,您从“构造函数”返回一个全新的对象(与上面 1 中的对象不同),这意味着没有实际区别。 this 的值在函数内部仍然会有所不同,但两者都会返回 false

new Foo() instanceof Foo;
Foo() instanceof Foo;

为了说明this 的区别,将以下内容添加到Foo

alert(this instanceof Foo)

当使用new 调用此警报true;在没有它的情况下调用时,false

此外,将对象分配给 Foo.prototype 是没有意义的,因为您永远不会创建任何可以使用它的 Foo 实例(因为,再次,您返回的内容与 Foo 完全不同)。

如果您要从Foo 返回自定义对象,那么您应该更喜欢没有new 的版本;无论如何,如果您要忽略它并返回完全不同的东西,那么创建 Foo 的新实例是没有意义的。

【讨论】:

  • 是的。我测试了两者都返回false。 “函数内部的 this 的值会有所不同”的任何小例子?
  • 它更好的解释。 new 创建 Foo 的实例,而没有 new 则只保留一个静态对象,可以随时使用。正确吗?
  • 此外,设置Foo.prototype 变得毫无意义,因为您创建的对象不是Foo 的实例。
  • @nnnnnn - 是的,我只是想发表类似的评论。我想我会更新我的答案。谢谢。
【解决方案2】:

这是一个很棒的链接:

Is Javascript "new" considered harmful?

另见:

http://phabricator.com/docs/phabricator/article/Javascript_Pitfalls.html

但这是最好的链接(实际上是您问题的答案:

http://www.crockford.com/javascript/inheritance.html

JavaScript 是一种无类、面向对象的语言,因此,它 使用原型继承而不是经典继承。这个可以 让受过传统面向对象培训的程序员感到困惑 像 C++ 和 Java 这样的语言...

【讨论】:

    【解决方案3】:

    函数中的 javascript new 关键字很奇怪。我能找到的对正在发生的事情的最好(唯一?)深入解释实际上是来自 Daniel Howard 的 this SO answer

    对于任何试图学习一些更高级的 Javascript 概念的人来说,都是必读的。

    顺便说一句,你可以在 js 中获得 真正 远不使用 new 关键字。请注意,使用 jquery 的代码基本上都没有依赖它。

    【讨论】:

      【解决方案4】:

      因为您从Foo 返回一个对象,所以使用new 没有任何效果。 Foo()new Foo() 的返回值将不是Foo 的实例;相反,它们将是您返回的任何值的类型的实例。

      如果您从构造函数返回任何† 对象或任何函数,则会看到相同的行为。 但是,如果 Foo 要返回:

      • 一个字符串
      • 一个数字
      • null
      • undefined(相当于什么都不返回)
      • this

      ...那么new Foo()的返回值Foo的一个实例。

      您可以在JSFiddle 上测试以下代码:

      function ReturnsString() { return "string"; }
      function ReturnsNumber() { return 1; }
      function ReturnsNull() { return null; }
      function ReturnsUndefined() { return void 0; }
      function ReturnsThis() { return this; }
      function ReturnsFunction() { return function() {}; }
      function ReturnsObject() { return {}; }
      
      alert("Results:"
          + "\nReturnsString: " + (new ReturnsString() instanceof ReturnsString)
          + "\nReturnsNumber: " + (new ReturnsNumber() instanceof ReturnsNumber)
          + "\nReturnsNull: " + (new ReturnsNull() instanceof ReturnsNull)
          + "\nReturnsUndefined: " + (new ReturnsUndefined() instanceof ReturnsUndefined)
          + "\nReturnsThis: " + (new ReturnsThis() instanceof ReturnsThis)
          + "\nReturnsFunction: " + (new ReturnsFunction() instanceof ReturnsFunction)
          + "\nReturnsObject: " + (new ReturnsObject() instanceof ReturnsObject)
      );
      

      ReturnsFunctionReturnsObject 构造函数都将显示 false 结果,这意味着它们在与 new 运算符一起使用时不会返回 instanceof

      所有其他构造函数do在与new 运算符一起使用时会返回一个instanceof

      † 如上所述,this 除外

      【讨论】:

      • 你的意思是,函数和对象不返回自身的实例。所以 Foo() 和 new Foo() 也没有。但是,如果他们返回其他东西。它们是它们自己实例的一部分!
      • @Umesh,完全正确。我发现这种行为非常不直观!谢天谢地Coffeescript。 ;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      相关资源
      最近更新 更多