Будет ли в JavaScript любая автономная внутренняя функция обрабатывать "this" как объект, для которого был вызван оригинальный метод?
В книге " Просветление JavaScript" (ссылка на предварительно опубликованную версию (стр. 85), но у меня есть опубликованная версия (глава 6.3), и в ней говорится то же самое), говорится, что любая внутренняя функция будет обрабатывать this
как глобальный объект (window
) в ECMA-3, но будет исправлено в ECMA-5.
Код ниже:
http://jsfiddle.net/javascriptenlightenment/9GJhu/
var myObject = {
func1: function() {
console.log(this); // logs myObject
var func2 = function() {
console.log(this) // logs window, and will do so from this point on
var func3 = function() {
console.log(this); // logs window, as it’s the head object
}();
}();
}
}
myObject.func1();
Но я думал, что нынешние Chrome, Firefox и node.js должны в значительной степени реализовывать ECMA-5, поэтому я попробовал в них приведенный выше код, и они все еще распечатывают глобальный объект внутри func2
а также func3
, Затем я добавил "use strict";
в func1
и на всякий случай также func2
а также func3
, Код: http://jsfiddle.net/9GJhu/6/ Теперь в Chrome и node.js, this
будет распечатан как undefined
, вместо myObject
, Итак, согласно книге, this
должно быть myObject
в ECMA-5. Что не так в коде выше?
3 ответа
Я могу ошибаться, но я нигде в спецификации не видел, что подразумевает эта книга.
Согласно спецификации ECMAScript 5.1 10.4.3 Ввод кода функции
- Если код функции является строгим кодом, установите ThisBinding на thisArg.
- Иначе, если thisArg имеет значение null или не определено, установите ThisBinding для глобального объекта.
- Иначе, если Type(thisArg) не является Object, установите для ThisBinding значение ToObject(thisArg).
- В противном случае установите ThisBinding на thisArg.
- Пусть localEnv будет результатом вызова NewDeclarativeEnvironment, передав в качестве аргумента значение внутреннего свойства [[Scope]] для F.
- Установите LexicalEnvironment в localEnv.
- Установите для VariableEnvironment значение localEnv.
- Пусть code будет значением внутреннего свойства F [[Code]].
- Выполните привязку декларации, используя код кода функции и argumentsList, как описано в 10.5.
Согласно (1.), так как ваш func2
а также func3
не имеет никакого контекста, и вы указали strict mode
ваш контекст будет установлен в undefined
, Без strict mode
и согласно (2.) this
будет установлен в window
,
Когда вы используете директиву use strict, ключевое слово this по умолчанию имеет значение undefined, в отличие от нестрого режима, где ключевое слово this по умолчанию ссылается на глобальный объект. Вам необходимо явно указать контекст.
На заметку, вам нужно только один раз объявить "использовать строгий".
Тот факт, что функции являются вложенными, ничего не значит. Они продолжают работать так же и не вложенные:
var myObject = {
func1: function() {
console.log(this); // logs myObject
}
}
myObject.func1();
var func2 = function() {
console.log(this) // logs window, and will do so from this point on
}();
var func3 = function() {
console.log(this); // logs window, as it’s the head object
}();
var myObject = {
func1: function() {
"use strict";
console.log(this); // logs myObject
}
}
myObject.func1();
var func2 = function() {
"use strict";
console.log(this) // logs window, and will do so from this point on
}();
var func3 = function() {
"use strict";
console.log(this); // logs window, as it’s the head object
}();
Первая функция вызывается с контекстом (как метод), и тогда "this" - это myObject.
другие функции вызываются без контекста (так же, как func2()
) и в этом случае ECMA-5 не разрешает не явную ссылку на глобальный объект через него.
Большинство браузеров не применяют ECMA-5 по умолчанию, потому что они не являются ретро-совместимыми, поскольку более строгие.