一、instanceof
和 constructor
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr.constructor == Array);// true
这样看似乎没有问题,但是有些情况 instanceof
和 constructor
并不能生效
当一个父页面中有一个框架,框架中引用了一个子页面,在子页面中声明了一个 array,并且将其赋值给父页面中的一个变量,这个时候用 instanceof
和 constructor
判断,就会不起作用
我们先看一下 instanceof
判断对象类型的原理
function _instanceof(L, R) {
let R = R.prototype;
let L = L.__proto__;
while(true) {
if (L == null) {
return false;
};
if (L == R) {
return true;
};
L = L.__proto__;
}
}
举个例子:
let iframe = document.createElement("iframe");
document.body.appendChild(iframe);
xArray = window.frames[0].Array;//iframe 中的 Array
let arr = [1, 2, 3];
let arrx = new xArray(4, 5, 6);
console.log(Array.prototype == xArray.prototype)//false
//-------------------------------------------
console.log(arrx instanceof Array);//false
console.log(arrx.constructor == Array);//false
//-------------------------------------------
console.log(arrx instanceof xArray);//true
console.log(arrx.constructor == xArray);//true
console.log(arr instanceof Array);//true
console.log(arr.constructor == Array);//true
console.log(arr instanceof xArray);//false
console.log(arr.constructor == xArray);//false
原因是:
- 如果页面中包含多个框架,那实际上就会有多个不同的全局执行环境,就会有多个不同版本的
Array
-
Array
属于引用类型数据,在传递过程中传递的是引用 - 每个页面的
Array
是不同的,他们的prototype
是不同的,构造函数也是不同的 - 参考上述
instanceof
的原理 - 所以在这个例子中,用
instanceof
判断会存在判断不准确的情况 - 所以,如果想用
instanceof
和constructor
判断类型,要求变量是在当前页面声明的
二、isArray()
let arr = [1, 2, 3];
console.log(Array.isArray(arr));//true
这种方法在 IE8 以下有兼容性问题
三、Object.prototype.toString()
let arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr));//[object Array]
可以通过这个方法封装一个可以返回变量类型的方法
let arr = [1, 2, 3];
function getType(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
};
console.log(getType(arr));//Array
网友评论