Подтвердить что ты не робот

Какова точка "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)"? Как объект (это) отличается от простого? И какая работа заключается в том, что здесь разница?

4b9b3361

Ответ 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, и он станет казаться очевидным:

  1. Пусть 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 относится к области видимости.