Проблема расширения класса с помощью прототипа объекта javascript - PullRequest
6 голосов
/ 29 июня 2011

У меня есть эта проблема ... B - базовый класс, а A - производный класс ... Событие, хотя A является производным от B, различные объекты A указывают на один и тот же объект B.

Я знаю, что назначил объект B прототипу A, чтобы сделать A потомком B.

Но разные объекты А должны иметь разное адресное пространство для хранения переменных, верно? Кто-нибудь может это исправить?

    function B(){

        this.obj = {};
    }

    function A(){

    }

    A.prototype = new B();

    var a = new A();
    var b = new A();
    var c = new A();

    console.log(a.obj == b.obj); //prints true
    console.log(a.obj === b.obj); //prints true

    a.obj.name = "stackoverflow";
    console.log(b.obj.name); //prints stackoverflow

Какое изменение я должен внести в этот код, чтобы получить следующий результат.

a.obj === b.obj  //must be false

a instanceof A;  //must be true
a instanceof B;  //must be true

Ответы [ 3 ]

4 голосов
/ 29 июня 2011

Вот почему у вас не должно быть изменяемых значений (особенно объектов или массивов) в прототипе - одно и то же значение будет общим для всех экземпляров объекта и может быть изменено в любом из них.Здесь вы можете избежать этой проблемы, используя Object.create , который не вызовет конструктор B при создании прототипа:

A.prototype = Object.create(B.prototype);

Затем следует вызвать конструктор Aконструктор B для каждого нового объекта:

function A() {
  B.call(this);
}

Для браузеров, которые не поддерживают Object.create(), вы можете эмулировать его, как указано в http://javascript.crockford.com/prototypal.html.

2 голосов
/ 29 июня 2011

Значения назначаются посредством ссылки, и, поскольку все экземпляры A используют тот же экземпляр B, что и их прототип, они все ссылаются на один и тот же 'B'.

Так что это именно то, что здесь ожидается.Одним из способов решения этой проблемы является добавление (например) метода 'initialize' к классу B ', который затем можно вызвать из конструктора A.

Вы также можете не используйте 'new B ()' для определения прототипа и используйте вместо него Object.create.Object.create не вызывает конструктор B, но затем вы можете вызвать родительский конструктор из A.

function A() {
   B.call(this);
}
1 голос
/ 29 июня 2011

Это часть прототипов в Javascript, я предлагаю вам прочитать эту превосходную ветку .

...