2012-01-03 79 views
4

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

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

new Foo(); 
Foo(); 

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

+0

请注意,设置'Foo.prototype = {}东西'是没有意义的,如果你打算从'富返回自己的对象()'函数,而不是去当你说'new Foo()'时,JS为你创建的对象。 – nnnnnn 2012-01-03 03:47:32

+2

@Bakudan - JavaScript是通过任何合理的术语定义来面向对象的。 – 2012-01-03 03:55:34

+0

@Bakudan,如果您有话要说(面向对象vs基于对象),请用新答案中的示例来证明它的正确性。它会帮助新手:) – 2012-01-03 03:59:54

回答

3

在正常情况下,应该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的新实例就毫无意义。

+0

是的。我测试了两个返回false。 “这个功能的价值会有所不同”的任何小例子? – 2012-01-03 03:36:55

+0

它更好的解释。 new创建Foo的实例,而没有新的只保留一个静态对象,可以随时使用。正确吗? – 2012-01-03 03:44:02

+0

此外,设置'Foo。原型“变得毫无意义,因为你创建的对象不是'Foo'的实例。 – nnnnnn 2012-01-03 03:48:26

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 ...

+0

谢谢@ paulsm4 :) – 2012-01-03 03:32:07

1

函数中的javascript new关键字很奇怪。最好的(只有?)深入解释我已经能够找到的事情实际上是Daniel Howard的this SO answer

对于任何想学习一些更高级的Javavscript概念的人来说,都应该要求阅读。

顺便说一句,你可以得到真的远在js永远不会使用新的关键字。注意基本上没有任何使用jQuery的代码依赖于它。

0

因为您从Foo返回对象,所以使用new不起作用。 Foo()new Foo()的返回值将为而非Foo的实例;相反,它们将是您返回的任何值的类型的实例。

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

  • 的字符串
  • 一些
  • null
  • undefined(同什么都没有返回)
  • this

...然后是的返回值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自己。

所有其他构造函数donew运算符一起使用时会自行返回instanceof本身。

†除this,正如我上面提到

+0

你的意思是,函数和对象不返回它自己的实例。所以Foo()和新的Foo()也不会。但是,如果他们返回别的东西。他们是他们自己实例的一部分! – 2012-01-03 04:23:28

+0

@ Umesh,这是完全正确的。我觉得这种行为非常不直观!感谢上帝[Coffeescript](http://coffeescript.org/)。 ;) – aeskr 2012-01-03 04:26:50