Непонятное поведение прототипа в JavaScript - PullRequest
2 голосов
/ 08 мая 2011

Я не понимаю, почему происходит следующее:

function Class() {}
Class.prototype.foo = {a: 1};
Class.prototype.bar = 1;

x = new Class();
y = new Class();

y.foo.a = 2;
y.bar = 2;

x.foo.a; //2
x.bar; //1

Когда я устанавливаю y.foo.a в 2, кажется, что он выполняет ту же операцию, что и y.constructor.prototype.foo.a = 2.С чего бы это, учитывая, что y.bar = 2 не влияет на y.constructor.prototype.bar?

Ответы [ 3 ]

3 голосов
/ 09 мая 2011

Вы смешиваете свойства прототипа со свойствами, локальными для экземпляра объекта. Используя y.bar = 2, вы назначаете свойство экземпляра (bar) для экземпляра y. При интерпретации свойства (bar) сначала ищется внутри самого экземпляра. Если он там не найден, поиск продолжается в прототипе экземпляров. Теперь вы присвоили bar y, поэтому y.bar = 2, но экземпляр x не знает об этом, поэтому для x поиск продолжается с использованием своего прототипа (это prototype.bar, все еще со значением 1).

Для y.foo.a в y отсутствует свойство экземпляра foo, поэтому оно было найдено в его прототипе. Там он найден, и свойству a назначено новое значение. Так как вы изменяете значение свойства Class.prototype foo, оно также отображается в x.

Если вы хотите изменить гриф в его прототипе (например, из экземпляра y), вам придется использовать прототип y constructor (то есть Class):

y.constructor.prototype.bar = 2;

Может г-н Дуглас Крокфорд может прояснить для вас вещи (пройдите примерно до 23 минуты в видео для наследования прототипа)?

0 голосов
/ 09 мая 2011

Вы читаете y.foo, но присваиваете y.bar.Это разные операции с разной семантикой.Параметр y.foo.bar должен сначала прочитать y.foo: он ищет значение foo в y, не может его найти, затем просматривает прототип y, обнаруживает объект и только затем изменяет этот объект,назначение y.bar просто ищет y, а затем изменяет его.x.bar и y.bar обозначают различные объекты, тогда как x.foo и и y.foo обозначают один и тот же объект.

0 голосов
/ 08 мая 2011

При чтении атрибута выполняется поиск в объекте-прототипе, если он не определен в главном объекте.

При установке атрибута он всегда задается для основного объекта и НИКОГДА не для объекта-прототипа.

Из-за этого плохая идея - определять что-либо, кроме функций или значений, которые никогда не изменятся в объектах-прототипах.

Чтобы действительно понять, что происходит, я рекомендую вам поэкспериментировать с атрибутом

 __proto__

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

...