I'm in ES5 strict mode, so the solution
function isArguments(item) {
return item.callee !== undefined;
}
unfortunately doesn't work.
function isArguments( item ) {
return Object.prototype.toString.call( item ) === '[object Arguments]';
}
_.isArguments.Symbol.toStringTag, which provides a way to customize the result of Object.prototype.toString. So it is possible to break this check in recent versions of JavaScript.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).
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');
}
Objectwith alengthproperty?alert(isArguments({"callee" : "test"}));- I agree with alex that checking for thelengthproperty is a reasonable compromise.