Checking types in Javascript is well known as a pretty unreliable process.
Good old typeof
operator is often useless when it comes to certain types of values:
typeof null; // "object" typeof []; // "object"
People often expect to see something like “null” in the former check and something like “array” in the latter one.
Fortunately, checking for null
is not that hard, despite useless typeof
, and is usually accomplished by strict-comparing value to null
:
value === null;
Checking for arrays, on the other hand, is a somewhat tricky business. There are usually two schools of thought – usinginstanceof
operator (or checking object’s constructor
property) and the-duck-typing way – checking for presence (or types) of certain set of properties (which are known to be present in array objects).
Obviously, both ways have their pros and cons.
1) `instanceof` operator / `constructor` property
instanceof
operator essentially checks whether anything from left-hand object’s prototype chain is the same object as what’s referenced by prototype
property of right-hand object. It sounds somewhat complicated but is easily understood from a simple example:
var arr = []; arr instanceof Array; // true
This statement returns `true` because Array.prototype
(being a prototype
property of a right-hand object) references the same object as an internal [[Prototype]] of left-hand object ([[Prototype]] is “visible” via arr.__proto__
in clients that have__proto__
extension). An alternative constructor
check, which I mentioned earlier, would usually look like:
var arr = []; arr.constructor == Array; // true
Both instanceof
and constructor
look very innocent and seem like great ways to check if an object is an array. If I remember correctly, latest jQuery is using constructor
:
An excerpt from jQuery (rev. 5917):
... isArray: function( arr ) { return !!arr && arr.constructor == Array; }
The problems arise when it comes to scripting in multi-frame DOM environments. In a nutshell, Array objects created within one iframe do not share [[Prototype]]’s with arrays created within another iframe. Their constructors are different objects and so both instanceof
and constructor
checks fail:
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); xArray = window.frames[window.frames.length-1].Array; var arr = new xArray(1,2,3); // [1,2,3] // Boom! arr instanceof Array; // false // Boom! arr.constructor === Array; // false
This “problem” was mentioned by Crockford as far as back in 2003. Doug suggested to try duck-typing and check for a type of one of the Array.prototype
methods – e.g.:
typeof myArray.sort == 'function'
Exactly for these reasons Javascript authors often resort to a second approach:
2) Duck-typing
We’ve been using it in Prototype.JS for quite some time now. Dean Edwards was using it in its base2, last time I looked at it.
An excerpt from Prototype.js (v. 1.6.0.3):
function isArray(object) { return object != null && typeof object === "object" && 'splice' in object && 'join' in object; }
By “fixing” multi-frame “problem”, this naive approach fails short in some of the trivial cases. If you were ever to have an object with splice
and join
properties, Object.isArray
would obviously detect that object as being an Array:
var testee = { splice: 1, join: 2 }; Object.isArray(testee); // true
Back in June, I was reading ECMA-262 specs and noticed that there was an easy way to get value of an internal [[Class]] property that every native object has. Object.prototype.toString
was defined like so:
Object.prototype.toString( )
When the toString method is called, the following steps are taken:
1. Get the [[Class]] property of this object.
2. Compute a string value by concatenating the three strings “[object ", Result (1), and "]“.
3. Return Result (2)
Contrary to Function.prototype.toString
which is implementation dependent and is NOT recommended to be relied upon,Object.prototype.toString
has a clearly defined behavior for all native objects.
15.3.4.2 Function.prototype.toString()
An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation string is implementation-dependent.
Just as a fun exercise, I wrote a simple __getClass
method, put it into an “experimental” folder and forgot about it : )
function __getClass(object) {
return Object.prototype.toString.call(object)
.match(/^\[object\s(.*)\]$/)[1];
};
A couple of weeks ago, though, someone created a ticket for Prototype.js – proposing an Object.isDate method. An implementation used constructor
check and so was vulnerable to cross-frame issues. This is when I remembered aboutgetClass
and its possible usage in isArray
, isDate
and other similar methods.
Specs mention that:
15.4.2.1 new Array([ item0[, item1 [,...]]])
…
The [[Class]] property of the newly constructed object is set to “Array”.
…
This means that creating isArray
function could not be simpler than:
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
The solution is not dependent on frames (since it checks internal [[Class]]) and is more robust than duck-typing approach. I have tested it on a handful of browsers (including some archaic and mobile ones) and was happy to find that all of them are indeed compliant in this regard.
Let’s hope this little “trick” serves as a remedy to cross-frame issues that authors struggle to find workarounds for : )
Happy new year!
相关推荐
instanceof 马克-to-win java视频的详细的描述介绍
JS 中 typeof 与 instanceof 的区别 在 JavaScript 中,typeof 和 instanceof 是两个常用的运算符,用来判断一个变量是否为空,或者是什么类型的。但是,这两个运算符之间还是有区别的。 typeof 运算符是一个一元...
### instanceof 关键字详解 在Java编程语言中,`instanceof`是一个十分重要的关键字,用于判断一个对象是否属于特定的类或接口。本文将详细解释`instanceof`的关键特性和使用场景,并通过示例代码加深理解。 #### ...
ES5的instanceof手写实现
if ($header instanceof Div && $body instanceof Div && $footer instanceof Header1) { // 生成页面 } else { throw new InvalidArgumentException('Incorrect element types'); } } } ``` 在这个例子中,`...
在JavaScript中,`instanceof`和`prototype`是两个非常重要的概念,它们涉及到对象的类型检测和继承机制。本文将深入探讨这两个关键字的关系及其在实际编程中的应用。 首先,我们来理解`instanceof`操作符。`...
15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof运算符.zip15.instanceof...
在JavaScript编程语言中,`instanceof` 和 `typeof` 是两个非常重要的操作符,用于判断变量的类型。它们各自有着不同的用途和用法,对于理解和调试代码至关重要。 首先,我们来详细了解一下`instanceof`操作符。`...
NULL 博文链接:https://chaoyi.iteye.com/blog/2079574
`instanceof`是JavaScript中的一个操作符,用于检查一个对象是否是特定构造函数的实例,或者更具体地说,是检查该对象的原型链上是否存在指定构造函数的`prototype`。这个操作符对于理解和处理对象继承关系非常关键...
本文将深入探讨四种常用的方法来识别和判断JavaScript中的数据类型:`typeof`、`instanceof`、`constructor`以及`prototype`。 ### 1. `typeof` `typeof`操作符是最常见的类型检测方式之一,它返回一个表示未经计算...
在面向对象编程中,向下转型和`instanceof`运算符是两种重要的概念,尤其是在多态性的实现中扮演关键角色。本文将深入探讨这两个主题,并结合Delphi编程语言的背景进行阐述,尽管`instanceof`运算符在Java中更为常见...
alert(a instanceof Array); // 返回true alert(a instanceof Object); // 返回true,因为Array是Object的子类 ``` 在上面的例子中,a是通过Array构造函数创建的数组实例,因此它既是Array的实例,也是Object的实例...
// 输出:a instanceof A: false ``` #### 示例2:对象实例检查 创建`B`类的实例`b`,然后检查`b`是否是`B`或`A`(因为`B`继承自`A`)的实例。在这种情况下,`b instanceof B`和`b instanceof A`都返回`true`。 `...
console.log('a instanceof A:', a instanceof A); console.log('a instanceof Object:', a instanceof Object); console.log('b instanceof B:', b instanceof B); console.log('b instanceof A:', b instanceof A)...
更具体地讲,当我们使用a instanceof b的表达式时,它会从a的原型(__proto__)开始,沿着原型链向上查找,直到到达原型链的顶端(null)为止。如果在这个过程中,遇到了b的prototype属性,那么表达式返回true,否则返回...
java instanceof运算符