class Cat {
string _name;
public Cat(string name) {
this._name = name;
}
}
Понимание области видимости в объектно-ориентированном Javascript
To read this aritcle in English
Читати цю статтю українською мовою
Читать эту статью на русском языке
Когда вы думаете о ключевом слове this, вы, наверное, считаете, что оно относится к текущему экземпляру класса. Это верно для большинства объектно-ориентированных языков, как C# и Java.
Например, я мог бы использовать this в C# таким образом:
Код:
В этом примере вы можете видеть иллюстрацию этого. В C# и Java, this всегда относится к экземпляру класса.
Итак, зная это, вы наверное решите, что та же ситуация будет в JavaScript и его this. Тем не менее, это не тот случай. Как и многое в написании объектно-ориентированного кода JavaScript, this ведет себя по-разному в некоторых ситуациях. В зависимости от того как вы используете this, он может не всегда указывать на экземпляр класса.
Код:
function Cat(name) {
this.Name = name;
}
this.Name = name;
}
В этом примере все работает точно так же как и в примере с C#, но давайте просмотрим на пример, где вещи могут работать неправильно, если не знать некоторых правил.
Код:
var wrong = new WrongClass();
wrong.publicMethod();
function WrongClass() {
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + this.publicProperty);
};
}
wrong.publicMethod();
function WrongClass() {
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + this.publicProperty);
};
}
В своих примерах, для вывода данных я использую объект console из Firebug.
Так что же не так с этим примером? Все выглядит правильно и должно работать, не так ли? Хорошо, оперируя предположением, что this всегда указывает на экземпляр класса, данный пример абсолютно верен. Тем не менее, мы используем JavaScript и не должны удивляться тому, что он делает вещи немного по-другому.
При вызове publicMethod(), было бы выведено:
Код:
>>> public method
>>> private method
>>> public property equals undefined
>>> private method
>>> public property equals undefined
Причина, по которой this.publicProperty равно undefined, в том, что когда вводится приватный метод, область видимости this меняется. Оно больше не означает текущий экземпляр класса "WrongClass", теперь оно означает текущий экземпляр функции "privateMethod".
Другая ситуация, где область видимости this должно было бы поменяться, это когда оно работает с обработчиком событий.
Код:
document.getElementById('button').onclick = function() {
alert(this.id);
}
alert(this.id);
}
В этом примере, this будет указывать на элемент "button". Существует множество случаев изменения области видимости, с которыми вы должны быть знакомы, когда имеете дело с объектно-ориентированными технологиями.
Вернемся к нашему примеру с "WrongClass". Я покажу Вам, как сделать, чтобы этот пример работал так, как вы этого ожидали вначале.
Код:
var right = new RightClass();
right.publicMethod();
function RightClass() {
var self = this;
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + self.publicProperty);
};
}
right.publicMethod();
function RightClass() {
var self = this;
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + self.publicProperty);
};
}
Вы заметили, что я объявил в коде новую переменную self. Я присвоил этой переменной значение this. Это позволило мне использовать переменную "self" в любое время, когда мне нужно обратиться к экземпляру класса, не беспокоясь при этом про область видимости.
Вы можете назвать вашу переменную как угодно, но "self" является общей практикой. Итак, сейчас в "privateMethod", когда вызывается "publicProperty", используется "self" и оно выведет соответствующее значение.
Код:
>>> public method
>>> private method
>>> public property equals props
>>> private method
>>> public property equals props
Оригинал: Understanding scope in object oriented JavaScript