ловушка self и this
сегодня я попался в восхитительную ловушку, возникшую в результате сочетания двух безобидных на первый взгляд техник: наследования и оптимизации. Конечно, в минимальных примерах кода в этой записи всё будет более заметно, тем более, что вы знаете, что ловушка тут есть.
итак, пример прототипного наследования:
function Parent() {
this.test = function() {};
}
function Child() {}
Child.prototype = new Parent();
child = new Child();
пример оптимизации для лучшей минификации и быстрого выполнения:
function Example() {
var NS = some.very.long.namespace,
self = this;
self.value = new NS.Value();
}
и комбинированный пример с ловушкой в действии:
function Parent() {
var self = this;
self.test = function() {
self.value = true;
};
}
function Child() {
var self = this;
self.value = false;
}
Child.prototype = new Parent();
child = new Child();
console.log(child.value); // false
child.test();
console.log(child.value); // false
Проблема возникает из-за того, что Child
и Child.prototype
— глобальные объекты. Когда создаётся Child.prototype
, конструктор Parent
сохраняет в self
именно этот объект, общий для всех экземпляров Child
. Естественно, он не совпадает ни с одним из этих экземпляров. И код внутри Parent
работает со свойствами именно этого объекта.
Конечно, если бы мы объявляли методы для наследования по-человечески, а не внутри конструктора, этой проблемы бы не было. Собственно, и оптимизация от сохранения this
в локальную переменную неизвестно какая, вероятно, этого делать не имеет смысла.