我访问了各种网站,但无法理解以下向自定义对象添加方法的方法之间的区别:
方法1:
function circle(radius){
this.radius = radius;
this.area = function(){ return 3.14*this.radius*this.radius;}
}
方法2:
function circle(radius){
this.radius = radius;
}
circle.prototype.area = function(){ return 3.14*this.radius*this.radius; }
其中一种方法是否有任何性能或设计问题而另一种方法没有?
答案 0 :(得分:12)
这是一种看待差异的方法:
var circle1 = circle(1);
var circle2 = circle(1);
alert(circle1.area == circle2.area);
对于Method1,您会看到false
,而Method2会在true
中产生。这是因为在第一种情况下,你为每个创建的对象分配一个新的闭包函数,两个对象最终会有不同的area
函数,即使它们都做同样的事情。在第二种情况下,对象使用其area
方法共享相同的原型对象,该方法在两种情况下当然都是相同的。
通常,Method2更好,原因如下:
Object.hasOwnProperty
还有一些缺点要记住。
这是一个常见错误的例子:
function NumberCollection()
{
}
NumberCollection.prototype = {
numbers: [],
sum: function()
{
var result = 0;
for (var i = 0; i < this.numbers.length; i++)
result += this.numbers[i];
return result;
}
}
var c1 = new NumberCollection();
c1.numbers.push(5);
alert(c1.sum()); // Shows 5
var c2 = new NumberCollection();
c2.numbers.push(6);
alert(c2.sum()); // Oops, shows 11 because c1.numbers and c2.numbers is the same
这里的正确方法是:
function NumberCollection()
{
this.numbers = [];
}
NumberCollection.prototype = {
numbers: null,
sum: function()
{
var result = 0;
for (var i = 0; i < this.numbers.length; i++)
result += this.numbers[i];
return result;
}
}
答案 1 :(得分:5)
第一种方法(让我们称之为类型1)将area()
函数添加到对象本身。每次使用circle
构造new
对象时,其正文将复制(!)到新实例。
第二种方法(类型2)将area()
函数添加到对象原型(原型在层次结构中是“一级”)。每次创建circle
的新实例时,只会复制radius
属性。
现在,当您在第二个对象的实例上调用area()
时,JavaScript无法在对象本身上找到该函数。现在它“上升”原型链并使用它找到的该名称的第一个函数。
现在这有几个含义:
area
的实现当它们存在时(通过更改原型),您不能为类型1执行此操作area
的功能,同时保留函数的“原始实现”