Как проверить, является ли объект объектом аргументов в JavaScript?

Я в строгом режиме ES5, поэтому решение

function isArguments(item) {
    return item.callee !== undefined;
}

к сожалению не работает.

Ответ 1

function isArguments( item ) {
    return Object.prototype.toString.call( item ) === '[object Arguments]';
}

Ответ 2

Ответ Уильяма прав, но некоторые объяснения могут быть полезными.

В ECMAScript 5 единственной характеристикой объектов Arguments является их внутренний [[Class]], как показано в §10.6 Аргумент Object:

Когда CreateArgumentsObject вызывается, следующие шаги: выполняется:

  • Пусть obj является результатом создания нового объекта ECMAScript.
  • Установить внутреннее свойство [[Class]] объекта obj на "Arguments".
  • Возврат obj

[[Класс]] является внутренним свойством, общим для всех объектов, значением которого является String, который классифицирует объект. Это объясняется в §8.6.2 Внутренние свойства и методы объекта:

Значение внутреннего свойства [[Class]] определяется этим спецификация для каждого типа встроенного объекта.

Значение внутреннего свойства [[Class]] используется внутри различать различные типы объектов.

Кроме того, обратите внимание, что объекты хоста не будут проблематичными:

Значение внутреннего свойства [[Class]] объекта-хоста может быть любое значение String, кроме одного из "Arguments", [...]

Поэтому, чтобы идентифицировать объект Arguments, вам нужно только проверить его класс.

Вы можете сделать это, используя §15.2.4.2 Object.prototype.toString:

  • Пусть O - результат вызова ToObject, передающего значение this в качестве аргумента.
  • Пусть класс является значением внутреннего свойства [[Class]] для O.
  • Возвращает значение String, которое является результатом объединения трех строк "[object ", class и "]".

Поэтому вы можете использовать Function.prototype.call, чтобы вызвать этот метод со значением this, установленным для объекта, который вы хотите проверить. Возвращаемая строка будет '[object Arguments]', если и только если это объект Arguments.

Object.prototype.toString.call(obj) == '[object Arguments]'

Обратите внимание, что это не является полностью надежным, потому что глобальный Object мог быть затенен локальным или глобальное свойство Object или его toString могло быть изменено.

Однако нет лучшего способа:

Обратите внимание, что эта спецификация не предоставляет никаких средств для программы для доступа к этому значению, за исключением Object.prototype.toString (см. 15.2.4.2).

Ответ 3

Генерация и сравнение строк для определения типа объекта немного нечеткая. Как и @bergi, я думаю, что Lodash делает это более удобным способом. Сжатый в одну функцию:

function isArguments(value) {
    return !!value && typeof value == 'object' && Object.prototype.hasOwnProperty.call(value, 'callee') && !Object.prototype.propertyIsEnumerable.call(value, 'callee');
}