14

是这个代码,

function Person() {
    function  myMethod() {
        alert ('hello');
    }
    this.method = myMethod;
}

相当于:

function Person() {    }
Person.prototype.method2  = function() {
    alert ('hello');
};

如果是,我应该使用哪种方法定义,为什么?

4

5 回答 5

14

在您的简单示例中,它们在功能上是等效的,但在幕后的工作方式却大不相同。函数的prototype属性实际上是“原型模板”。它说“每当制作一个对象并且我被用作对象的构造函数时,就给他们这个对象作为他们的原型”。

因此Person,在您的第二个示例中创建的所有 s 共享该method2方法的相同副本。

在第一个示例中,解释器每次遇到function关键字时,都会创建一个新的函数对象。所以在第一个例子中,每个实例Person都有自己的myMethod方法副本。绝大多数时候这无关紧要。但是第一种方法使用更多的内存,有时这确实很重要。

在更有趣的情况下,它们在功能上并不等效。在第一个示例中,myMethod可以访问定义在 中的局部变量Person,但第二个示例不能,作为一个区别。

于 2012-05-08T14:10:30.860 回答
2

在第一种情况下,当您创建一个新人时var person1 = new Person();,它将拥有自己的myMethod. 如果你创建了 100 个 Person 对象,它们每个都有自己的这个方法的副本。

使用原型,每个新的 Person 对象都将共享方法定义。由于该方法只有一个副本,因此内存效率要高得多。

如果您打算拥有多个 Person 对象,则第二种方法更好。但是如果只有几个 Person 对象,那也没关系。

于 2012-05-08T14:11:57.793 回答
1

它不完全等价。

在这两种情况下,您都在全局命名空间中定义了一个函数(构造函数)Person()

在第一种情况下,您在函数myMethod()内部的闭包中定义一个新Person()函数。通常,myMethod()函数/构造函数完成后该函数将不可用Person()。但是,在这种情况下,您将其分配给this.method. 因此,当您运行构造函数时

var myPerson = new Person();

创建一个新对象,然后调用该Person()函数并将其this设置为新对象。因此,您的新对象会收到一个绑定method了函数的字段。myMethod

在第二种情况下,method2Person.prototype. 在这种情况下,当您调用

var myPerson = new Person();

新对象内部不会直接定义任何字段(因为您this在函数中什么也不做Person)。但是,每个对象都包含对其原型的引用。如果对象是通过调用创建的Person(),则此引用设置为Person.prototype。因此,您的对象最终将包含method2,尽管不是直接在其自身中,而是在原型中。所以当你打电话

myPerson.method2();

解释器method2在对象内部myPerson寻找并没有找到任何东西,然后它查看 的原型myPerson,即Person.prototype并找到method2,所以它调用它。

长话短说:首先你的构造函数创建了方法,所以每次调用构造函数时,都会创建一个新方法并将其插入到新对象中。在第二种情况下,方法存储在原型中,因此您创建的每个对象都将引用您的方法的同一实例。

于 2012-05-08T14:16:02.410 回答
0

不,它们不相等。虽然,它们很相似。第一种方法将为myMethod每个new Person()创建的函数创建一个新函数。

第二种方法将具有一个method2由所有人“共享”的功能Person's

于 2012-05-08T14:09:54.393 回答
0

它们具有相似的功能,但您应该使用第二种方法(原型),因为当您使用new Person()每个对象创建一个对象时,每个对象都将共享相同的内容method2,但使用第一种方法,每个新对象都将拥有自己的myMethod(),这将消耗 moe 内存。

几天前我问了一个类似的问题并得到了 这个答案

于 2012-05-08T14:12:55.943 回答