Понимание области видимости в объектно-ориентированном JavaScript
Метки: веб-разработка, javascript
Розуміння області видимості в об’єктно-орієнтованому JavaScript
Understanding scope in object oriented JavaScript
| ← 6 инструментов чтобы быть эффективным Web-разработчиком | 10 шагов к быстрому изучению нового языка программирования → |
Когда вы думаете о ключевом слове this, вы, наверное, считаете, что оно относится к текущему экземпляру класса. Это верно для большинства объектно-ориентированных языков, как C# и Java.
Например, я мог бы использовать this в C# таким образом:
Убрать подсветку кода
В этом примере вы можете видеть иллюстрацию этого. В C# и Java, this всегда относится к экземпляру класса.
Итак, зная это, вы наверное решите, что та же ситуация будет в JavaScript и его this. Тем не менее, это не тот случай. Как и многое в написании объектно-ориентированного кода JavaScript, this ведет себя по-разному в некоторых ситуациях. В зависимости от того как вы используете this, он может не всегда указывать на экземпляр класса.
Убрать подсветку кода
В этом примере все работает точно так же как и в примере с C#, но давайте просмотрим на пример, где вещи могут работать неправильно, если не знать некоторых правил.
Убрать подсветку кода
В своих примерах, для вывода данных я использую объект console из Firebug.
Так что же не так с этим примером? Все выглядит правильно и должно работать, не так ли? Хорошо, оперируя предположением, что this всегда указывает на экземпляр класса, данный пример абсолютно верен. Тем не менее, мы используем JavaScript и не должны удивляться тому, что он делает вещи немного по-другому.
При вызове publicMethod(), было бы выведено:
Убрать подсветку кода
Причина, по которой this.publicProperty равно undefined, в том, что когда вводится приватный метод, область видимости this меняется. Оно больше не означает текущий экземпляр класса "WrongClass", теперь оно означает текущий экземпляр функции "privateMethod".
Другая ситуация, где область видимости this должно было бы поменяться, это когда оно работает с обработчиком событий.
Убрать подсветку кода
В этом примере, this будет указывать на элемент "button". Существует множество случаев изменения области видимости, с которыми вы должны быть знакомы, когда имеете дело с объектно-ориентированными технологиями.
Вернемся к нашему примеру с "WrongClass". Я покажу Вам, как сделать, чтобы этот пример работал так, как вы этого ожидали вначале.
Убрать подсветку кода
Вы заметили, что я объявил в коде новую переменную self. Я присвоил этой переменной значение this. Это позволило мне использовать переменную "self" в любое время, когда мне нужно обратиться к экземпляру класса, не беспокоясь при этом про область видимости.
Вы можете назвать вашу переменную как угодно, но "self" является общей практикой. Итак, сейчас в "privateMethod", когда вызывается "publicProperty", используется "self" и оно выведет соответствующее значение.
Убрать подсветку кода
Оригинал: Understanding scope in object oriented JavaScript
Например, я мог бы использовать this в C# таким образом:
Убрать подсветку кода
1 2 3 4 5 6 | class Cat { string _name; public Cat(string name) { this._name = name; } } |
В этом примере вы можете видеть иллюстрацию этого. В C# и Java, this всегда относится к экземпляру класса.
Итак, зная это, вы наверное решите, что та же ситуация будет в JavaScript и его this. Тем не менее, это не тот случай. Как и многое в написании объектно-ориентированного кода JavaScript, this ведет себя по-разному в некоторых ситуациях. В зависимости от того как вы используете this, он может не всегда указывать на экземпляр класса.
Убрать подсветку кода
1 2 3 | function Cat(name) { this.Name = name; } |
В этом примере все работает точно так же как и в примере с C#, но давайте просмотрим на пример, где вещи могут работать неправильно, если не знать некоторых правил.
Убрать подсветку кода
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); }; } |
В своих примерах, для вывода данных я использую объект console из Firebug.
Так что же не так с этим примером? Все выглядит правильно и должно работать, не так ли? Хорошо, оперируя предположением, что this всегда указывает на экземпляр класса, данный пример абсолютно верен. Тем не менее, мы используем JavaScript и не должны удивляться тому, что он делает вещи немного по-другому.
При вызове publicMethod(), было бы выведено:
Убрать подсветку кода
1 2 3 | >>> public method
>>> private method
>>> public property equals undefined |
Причина, по которой this.publicProperty равно undefined, в том, что когда вводится приватный метод, область видимости this меняется. Оно больше не означает текущий экземпляр класса "WrongClass", теперь оно означает текущий экземпляр функции "privateMethod".
Другая ситуация, где область видимости this должно было бы поменяться, это когда оно работает с обработчиком событий.
Убрать подсветку кода
1 2 3 | document.getElementById('button').onclick = function() { alert(this.id); } |
В этом примере, this будет указывать на элемент "button". Существует множество случаев изменения области видимости, с которыми вы должны быть знакомы, когда имеете дело с объектно-ориентированными технологиями.
Вернемся к нашему примеру с "WrongClass". Я покажу Вам, как сделать, чтобы этот пример работал так, как вы этого ожидали вначале.
Убрать подсветку кода
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); }; } |
Вы заметили, что я объявил в коде новую переменную self. Я присвоил этой переменной значение this. Это позволило мне использовать переменную "self" в любое время, когда мне нужно обратиться к экземпляру класса, не беспокоясь при этом про область видимости.
Вы можете назвать вашу переменную как угодно, но "self" является общей практикой. Итак, сейчас в "privateMethod", когда вызывается "publicProperty", используется "self" и оно выведет соответствующее значение.
Убрать подсветку кода
1 2 3 | >>> public method
>>> private method
>>> public property equals props |
Оригинал: Understanding scope in object oriented JavaScript
Рейтинг:




<< Вы можете поставить оценку этой статьеПодобные статьи:
6 инструментов чтобы быть эффективным Web-разработчиком
Введение в искусство модульного тестирования в PHP
Интеграция FCKeditor в Zend_Form
Автоматизированное тестирование с использованием Zend Framework
Паттерн кэширования для моделей
Обсуждение статьи:
apapacy [2009-06-13]
Не думаю что происходит понимание области видимости.
Скорее просто используется неоправданное замыкание.
Больше заявленной теме соответсвует такой код (к Вам как переводчику это замечание не относится)
var right = new RightClass();
right.publicMethod();
function RightClass() {
//var self = this;
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
this.privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + this.publicProperty);
};
}
moroz1999 [2009-07-19]
apapacy: приведённый вами вариант не работает и работать не может, поскольку privateMethod вызывается через this, не будучи на этот самый this предварительно назначенным.