wwww
wwww

Reputation: 395

How do I check whether an object is an arguments object in JavaScript?

I'm in ES5 strict mode, so the solution

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

unfortunately doesn't work.

Upvotes: 13

Views: 4080

Answers (3)

Kristian Kraljic
Kristian Kraljic

Reputation: 834

Generating and comparing strings to determine the type of an object is a little fuzzy. Like @bergi suggested, I think Lodash is doing it a more convenient way. Condensed into one function it is:

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

Upvotes: 1

Oriol
Oriol

Reputation: 288280

William's answer is right, but some explanations may be useful.

In ECMAScript 5, the only thing that characterizes Arguments objects is their internal [[Class]], as seen in §10.6 Arguments Object:

When CreateArgumentsObject is called the following steps are performed:

  • Let obj be the result of creating a new ECMAScript object.
  • Set the [[Class]] internal property of obj to "Arguments".
  • Return obj

[[Class]] is an internal property common to all objects, whose value is a String which classifies the object. This is explained in §8.6.2 Object Internal Properties and Methods:

The value of the [[Class]] internal property is defined by this specification for every kind of built-in object.

The value of a [[Class]] internal property is used internally to distinguish different kinds of objects.

Moreover, note that host objects won't be problematic:

The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", [...]

Therefore, to identify an Arguments object you only need to check its class.

You can do that using §15.2.4.2 Object.prototype.toString:

  • Let O be the result of calling ToObject passing the this value as the argument.
  • Let class be the value of the [[Class]] internal property of O.
  • Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".

Therefore, you can use Function.prototype.call to call that method with the this value set to the object you want to check. The returned string will be '[object Arguments]' if, and only if, it's an Arguments object.

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

Note that isn't completely foolproof, because the global Object could have been shadowed by a local one, or the global Object or its toString property could have been modified.

However, there is no better way:

Note that this specification does not provide any means for a program to access that value except through Object.prototype.toString (see 15.2.4.2).

Upvotes: 9

Will
Will

Reputation: 20235

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

Upvotes: 29

Related Questions