Какова точка "var t = Object (this)" в официальной реализации forEach?
Согласно MDC, ECMA-262, 5-е издание дает реализацию forEach как:
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisp */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
fun.call(thisp, t[i], i, t);
}
};
}
Может ли кто-нибудь сказать мне, что делает строка "var t = Object (this)"? Как объект (это) отличается от простого? И какая работа заключается в том, что здесь разница?
Ответы
Ответ 1
Реализации Mozilla просто пытаются точно эмулировать шаги, описанные в спецификации, Object(this);
эмулирует первый шаг, вызывая ToObject
внутренний метод:
От Array.prototype.forEach
15.4.4.18:
....
При вызове метода forEach один или два аргумента, следующие предпринимаются шаги:
-
Пусть O - результат вызова ToObject передает это значение как аргумент.
-
Пусть lenValue является результатом вызова внутреннего метода O [[Get]] с аргументом "length".
-
Пусть len - ToUint32 (lenValue).
....
Вызов конструктора объектов как функции за кулисами он выполняет преобразование типов, внутренне, как описано в 15.2.1.1 вызывается метод ToObject
.
Есть такие вещи, как если бы вы внимательно посмотрели, например, на строку:
var len = t.length >>> 0;
Они эмулируют вызов внутреннего метода ToUint32, как описано в шаге 3, используя беззнаковый оператор сдвига вправо (>>>
).
Edit:
Предыдущие строки отвечают, почему реализация Mozilla делает это таким образом.
Вы можете задаться вопросом, почему спецификация ECMAScript. необходимо вызвать ToObject
, проверить шаг 2, и он станет казаться очевидным:
- Пусть lenValue является результатом вызова внутреннего метода O [[Get]] с аргументом "length".
Спектр. должно гарантировать, что значение this
, используемое при вызове функции, является объектом, поскольку примитивные значения не имеют внутренних методов, как вы можете видеть на шаге 2, необходим внутренний метод [[Get]](P)
, чтобы получить значение свойства length
.
Это делается потому, что для строгих функций (а также для встроенных функций) вы можете установить примитивные значения как значение функции this
, например:
(function () {"use strict"; return typeof this; }).call(5); // "number"
В то время как для нестрогих функций значение this
всегда преобразуется в Object:
(function () { return typeof this; }).call(5); // "object"
Ответ 2
Вероятная причина s9.9 ECMA-262, об абстрактной операции ToObject
(как упоминается @CMS).
При вызове значения null
или undefined
он заставляет бросать TypeError
, но те, которые уже захвачены предыдущими строками.
Однако, если вы должны были позвонить:
Array.prototype.forEach.call("123", func() { ... } )
это не удастся, если бы это было не для принуждения типа. В частности, вы не можете вызвать index in this
, если this
является string
, но вы можете вызвать его по результату ToObject
.
Этот текст из 15.4.4.18, вероятно, имеет значение:
Функция forEach намеренно является общей; он не требует, чтобы это значение было объектом Array. Поэтому он может быть передан другим типам объектов для использования в качестве метода. Может ли функция forEach успешно применяться к объекту хоста, зависит от реализации.
Ответ 3
Я пишу var t = this;
все время. Я нахожу, что область этого иногда зависит от браузера; в любом случае не всегда понятно, что браузер будет делать с ключевым словом, так как сфера изменений изменяется, особенно в закрытии методов. Мне нравится опускать мой JS-код на уровень детского сада, чтобы оставить минимальное пространство для отдельных браузеров, чтобы делать неуловимые вещи.
Чтобы гарантировать, что я всегда имею дело с this
, с которым я хочу иметь дело при передаче this
методу или чему-то, я всегда пишу var t = this;
в качестве первой строки моего метода. Затем t
является переменной и подчиняется предсказуемым правилам области видимости переменной, а ее указатель назначается во время назначения объекту, обозначенному этим в то время. Таким образом, мне не нужно беспокоиться о методе, другом объекте или несовместимом интерпретаторе браузера, о котором this
относится к области видимости.