Простой вопрос о клоне в JavaScript - PullRequest
2 голосов
/ 08 июля 2011

У меня есть точка

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();
    };
};

Но второе утверждение не выполняется для моей реализации.Как мне это переопределить?

Ответы [ 2 ]

4 голосов
/ 08 июля 2011

Если бы свойства были только 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;
}

но это будет не свойства глубокой копии. Это работает только для примитивных значений.

Если вы действительно хотите глубокое копирование свойств, это может стать намного более сложным. К счастью, об этом уже спрашивали раньше: Как сделать Deep clone в javascript


Объяснение того, почему ваш метод клонирования не работает:

Прототип цепочки p2 будет выглядеть так:

 +-----------+      +-----------+
 |Instance p2|      |Instance p1|
 |           |----->|x=2        |
 |           |      |y=3        |
 +-----------+      +-----------+

, поэтому, если вы установите p1.x = 6, это будет:

 +-----------+      +-----------+
 |Instance p2|      |Instance p1|
 |           |----->|x=6        |
 |           |      |y=3        |
 +-----------+      +-----------+

Пока p2 не имеет собственных x или y свойств, они всегда будут ссылаться на свойства прототипа, который имеет вид p1.

1 голос
/ 08 июля 2011
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;
    };
};

Пример: http://jsfiddle.net/HPtmk/

...