是这个代码,
function Person() {
function myMethod() {
alert ('hello');
}
this.method = myMethod;
}
相当于:
function Person() { }
Person.prototype.method2 = function() {
alert ('hello');
};
如果是,我应该使用哪种方法定义,为什么?
是这个代码,
function Person() {
function myMethod() {
alert ('hello');
}
this.method = myMethod;
}
相当于:
function Person() { }
Person.prototype.method2 = function() {
alert ('hello');
};
如果是,我应该使用哪种方法定义,为什么?
在您的简单示例中,它们在功能上是等效的,但在幕后的工作方式却大不相同。函数的prototype
属性实际上是“原型模板”。它说“每当制作一个对象并且我被用作对象的构造函数时,就给他们这个对象作为他们的原型”。
因此Person
,在您的第二个示例中创建的所有 s 共享该method2
方法的相同副本。
在第一个示例中,解释器每次遇到function
关键字时,都会创建一个新的函数对象。所以在第一个例子中,每个实例Person
都有自己的myMethod
方法副本。绝大多数时候这无关紧要。但是第一种方法使用更多的内存,有时这确实很重要。
在更有趣的情况下,它们在功能上并不等效。在第一个示例中,myMethod
可以访问定义在 中的局部变量Person
,但第二个示例不能,作为一个区别。
在第一种情况下,当您创建一个新人时var person1 = new Person();
,它将拥有自己的myMethod
. 如果你创建了 100 个 Person 对象,它们每个都有自己的这个方法的副本。
使用原型,每个新的 Person 对象都将共享方法定义。由于该方法只有一个副本,因此内存效率要高得多。
如果您打算拥有多个 Person 对象,则第二种方法更好。但是如果只有几个 Person 对象,那也没关系。
它不完全等价。
在这两种情况下,您都在全局命名空间中定义了一个函数(构造函数)Person()
。
在第一种情况下,您在函数myMethod()
内部的闭包中定义一个新Person()
函数。通常,myMethod()
函数/构造函数完成后该函数将不可用Person()
。但是,在这种情况下,您将其分配给this.method
. 因此,当您运行构造函数时
var myPerson = new Person();
创建一个新对象,然后调用该Person()
函数并将其this
设置为新对象。因此,您的新对象会收到一个绑定method
了函数的字段。myMethod
在第二种情况下,method2
在Person.prototype
. 在这种情况下,当您调用
var myPerson = new Person();
新对象内部不会直接定义任何字段(因为您this
在函数中什么也不做Person
)。但是,每个对象都包含对其原型的引用。如果对象是通过调用创建的Person()
,则此引用设置为Person.prototype
。因此,您的对象最终将包含method2
,尽管不是直接在其自身中,而是在原型中。所以当你打电话
myPerson.method2();
解释器method2
在对象内部myPerson
寻找并没有找到任何东西,然后它查看 的原型myPerson
,即Person.prototype
并找到method2
,所以它调用它。
长话短说:首先你的构造函数创建了方法,所以每次调用构造函数时,都会创建一个新方法并将其插入到新对象中。在第二种情况下,方法存储在原型中,因此您创建的每个对象都将引用您的方法的同一实例。
不,它们不相等。虽然,它们很相似。第一种方法将为myMethod
每个new Person()
创建的函数创建一个新函数。
第二种方法将具有一个method2
由所有人“共享”的功能Person's
。
它们具有相似的功能,但您应该使用第二种方法(原型),因为当您使用new Person()
每个对象创建一个对象时,每个对象都将共享相同的内容method2
,但使用第一种方法,每个新对象都将拥有自己的myMethod()
,这将消耗 moe 内存。
几天前我问了一个类似的问题并得到了 这个答案。