ловушка 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 в локальную переменную неизвестно какая, вероятно, этого делать не имеет смысла.

Артемий Трегубенко,

comments powered by Disqus