我有一个点
function Point(x, y) {
this.x = x;
this.y = y;
};
如你所见,它是可变的。所以我可以改变它的属性,比如
var p = new Point(2, 3);
p.x = 6;
我想添加克隆方法,以便预期的行为是
var p1 = new Point(2, 3);
var p2 = p1.clone();
p1.x = 6;
assert p1 != p2; //first assertion. pseudocode.
assert p2.x == 2; //second assertion. pseudocode.
为了实现clone()
我以下一种方式重写Point
function Point(x, y) {
this.x = x;
this.y = y;
this.clone = function () {
function TrickyConstructor() {
}
TrickyConstructor.prototype = this;
return new TrickyConstructor();
};
};
但是我的实施失败了第二个断言。我应该如何重新实现呢?
答案 0 :(得分:4)
如果属性仅为x
和y
,我会这样做:
function Point(x, y) {
this.x = x;
this.y = y;
};
Point.prototype.clone = function() {
return new Point(this.x, this.y);
}
请注意,我将clone
方法附加到Point.prototype
。这对下一个工作方法很重要:
如果没有,则必须创建一个新实例,并将所有属性复制到新实例:
Point.prototype.clone = function() {
var clone = new Point(this.x, this.y);
for(var prop in this) {
if(this.hasOwnProperty(prop)) {
clone[prop] = this[prop];
}
}
return clone;
}
但这将是不深层复制属性。这仅适用于原始值。
如果您真的想要深层复制属性,这可能会变得更加复杂。幸运的是,之前已经问过这个问题:How to Deep clone in javascript
解释克隆方法不起作用的原因:
p2
的原型链将如下所示:
+-----------+ +-----------+
|Instance p2| |Instance p1|
| |----->|x=2 |
| | |y=3 |
+-----------+ +-----------+
所以如果你设置p1.x = 6
,它将是:
+-----------+ +-----------+
|Instance p2| |Instance p1|
| |----->|x=6 |
| | |y=3 |
+-----------+ +-----------+
只要p2
没有拥有 x
或y
属性,它们就会始终引用恰好是{{{}的原型。 1}}。
答案 1 :(得分:1)
function Point(x, y) {
this.x = x;
this.y = y;
this.clone = function () {
var newPoint = {};
for (var key in this) {
newPoint[key] = this[key];
}
return newPoint;
};
};