这是代码,
function Person() {
function myMethod() {
alert ('hello');
}
this.method = myMethod;
}
相当于:
function Person() { }
Person.prototype.method2 = function() {
alert ('hello');
};
如果是,我应该使用哪种方法定义以及为什么?
答案 0 :(得分:13)
它们在您的简单示例中功能相同,但幕后工作方式却截然不同。函数上的prototype
属性实际上是“原型模板”。它说“无论何时制作一个对象,我都被用作对象的构造函数,给它们这个对象作为它们的原型”。
因此,在第二个示例中创建的所有Person
共享method2
方法的同一副本。
在第一个示例中,每次解释器遇到function
关键字时,它都会创建一个新的函数对象。因此,在第一个示例中,Person
的每个实例都有自己的myMethod
方法副本。绝大多数时候这无关紧要。但是这第一种方法使用更多的内存,有时这很重要。
在更有趣的案例中,它们在功能上并不相同。在第一个示例中,myMethod
可以访问Person
中定义的局部变量,但第二个示例不能作为一个区别。
答案 1 :(得分:2)
在第一个方案中,当您创建新人var person1 = new Person();
时,它将拥有自己的myMethod
副本。如果您创建100个Person对象,则每个对象都有自己的此方法副本。
使用原型,每个新的Person对象将共享方法定义。这样的内存效率更高,因为只有一个方法副本。
如果您计划使用多个Person对象,第二种方式更好..但如果只有少数Person对象,那就没那么重要了。
答案 2 :(得分:1)
它并不完全等同。
在这两种情况下,您都可以在全局命名空间中定义一个函数(构造函数)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
,所以它称之为。
长话短说:在第一个构造函数创建方法时,每次调用构造函数时,都会创建一个新方法并将其插入到新对象中。在第二种情况下,该方法存储在原型中,因此您创建的每个对象都将引用您方法的同一实例。
答案 3 :(得分:0)
不,他们不等同。虽然,他们是相似的。第一种方法将为每个创建的myMethod
创建一个新函数new Person()
。
第二种方法将有一个由method2
“共享”的函数Person's
。
答案 4 :(得分:0)
它们具有相似的功能,但您应该使用第二种方法(原型),因为当您使用new Person()
创建对象时,每个对象将共享相同的method2
,但使用第一种方法,每个新对象将让它拥有自己的myMethod()
消耗moe记忆。
前几天我问了一个类似的问题并得到了 this answer。