renovations
This commit is contained in:
parent
c7d4c7e3ff
commit
e1948130f6
170 changed files with 1496 additions and 1161 deletions
|
@ -96,9 +96,9 @@ user = null;
|
|||
admin.sayHi(); // упс! внутри sayHi обращение по старому имени, ошибка!
|
||||
```
|
||||
|
||||
**Использование `this` гарантирует, что функция работает именно с тем объектом, в контексте которого вызвана!**
|
||||
Использование `this` гарантирует, что функция работает именно с тем объектом, в контексте которого вызвана.
|
||||
|
||||
Через `this` метод может обратиться к любому свойству объекта, а, при желании, и передать объект куда-либо:
|
||||
Через `this` метод может не только обратиться к любому свойству объекта, но и передать куда-то ссылку на сам объект целиком:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -112,8 +112,8 @@ var user = {
|
|||
*/!*
|
||||
};
|
||||
|
||||
function showName(obj) {
|
||||
alert( obj.name );
|
||||
function showName(namedObj) {
|
||||
alert( namedObj.name );
|
||||
}
|
||||
|
||||
user.sayHi(); // Василий
|
||||
|
@ -157,7 +157,7 @@ admin['g'](); // Админ (не важно, доступ к объекту ч
|
|||
*/!*
|
||||
```
|
||||
|
||||
**Значение `this` не зависит от того, как функция была создана, оно определяется исключительно в момент вызова.**
|
||||
Итак, значение `this` не зависит от того, как функция была создана, оно определяется исключительно в момент вызова.
|
||||
|
||||
## Значение this при вызове без контекста
|
||||
|
||||
|
@ -176,7 +176,9 @@ function func() {
|
|||
func();
|
||||
```
|
||||
|
||||
В современном стандарте языка это поведение изменено, вместо глобального объекта `this` будет `undefined`.
|
||||
Таково поведение в старом стандарте.
|
||||
|
||||
А в режиме `use strict` вместо глобального объекта `this` будет `undefined`:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -188,12 +190,13 @@ function func() {
|
|||
func();
|
||||
```
|
||||
|
||||
Это стоит иметь в виду для общего развития, но обычно если в функции используется `this`, то она, всё же, проектируется для вызова в контексте объекта.
|
||||
Обычно если в функции используется `this`, то она, всё же, служит для вызова в контексте объекта, так что такая ситуация -- скорее исключение.
|
||||
|
||||
[warn header="`this` теряется при операциях с методом"]
|
||||
Ещё раз обратим внимание: контекст `this` никак не привязан к функции, даже если она создана в объявлении объекта.
|
||||
## Ссылочный тип
|
||||
|
||||
Чтобы `this` передался правильно, нужно вызвать функцию именно через точку (или квадратные скобки). Любой более хитрый вызов приведёт к потере контекста, например:
|
||||
Контекст `this` никак не привязан к функции, даже если она создана в объявлении объекта. Чтобы `this` передался, нужно вызвать функцию именно через точку (или квадратные скобки).
|
||||
|
||||
Любой более хитрый вызов приведёт к потере контекста, например:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
|
@ -204,25 +207,38 @@ var user = {
|
|||
};
|
||||
|
||||
user.hi(); // Вася (простой вызов работает)
|
||||
|
||||
*!*
|
||||
// а теперь вызовем user.hi или user.bye в зависимости от имени
|
||||
(user.name == "Вася" ? user.hi : user.bye)(); // undefined
|
||||
*/!*
|
||||
```
|
||||
|
||||
В последней строке примера метод получен в результате выполнения тернарного оператора и тут же вызван. При этом `this` теряется.
|
||||
В последней строке примера метод получен в результате выполнения тернарного оператора и тут же вызван. Но `this` при этом теряется.
|
||||
|
||||
Иначе говоря, такой вызов эквивалентен двум строкам:
|
||||
Если хочется понять, почему, то причина кроется в деталях работы вызова `obj.method()`.
|
||||
|
||||
```js
|
||||
var method = (user.name == "Вася" ? user.hi : user.bye);
|
||||
method(); // без this
|
||||
```
|
||||
Он ведь, на самом деле, состоит из двух независимых операций: точка `.` -- получение свойства и скобки `()` -- его вызов (предполагается, что это функция).
|
||||
|
||||
[/warn]
|
||||
|
||||
## Задачи
|
||||
Функция, как мы говорили раньше, сама по себе не запоминает контекст. Чтобы "донести его" до скобок, JavaScript применяет "финт ушами" -- точка возвращает не функцию, а значение специального "ссылочного" типа [Reference Type](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-reference-specification-type).
|
||||
|
||||
Этот тип представляет собой связку "base-name-strict", где:
|
||||
<ul>
|
||||
<li>*base* -- как раз объект,</li>
|
||||
<li>*name* -- имя свойства,</li>
|
||||
<li>*strict* -- вспомогательный флаг для передачи `use strict`.</li>
|
||||
</ul>
|
||||
|
||||
То есть, ссылочный тип (Reference Type) -- это своеобразное "три-в-одном". Он существует исключительно для целей спецификации, мы его не видим, поскольку любой оператор тут же от него избавляется:
|
||||
|
||||
<ul>
|
||||
<li>Скобки `()` получают из `base` значение свойства `name` и вызывают в контексте base.</li>
|
||||
<li>Другие операторы получают из `base` значение свойства `name` и используют, а остальные компоненты игнорируют.</li>
|
||||
</ul>
|
||||
|
||||
Поэтому любая операция над результатом операции получения свойства, кроме вызова, приводит к потере контекста.
|
||||
|
||||
Аналогично работает и получение свойства через квадратные скобки `obj[method]`.
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue