万事开头难,克服自己的拖延症,第一篇js基础复习篇start!
希望和各位同行交流,同时欢迎各位指出不足和错误之处。
首先,typeof肯定是不行的
对于一些基本类型,typeof是可以判断出数据类型,但是判断一些引用类型时候,不能具体到具体哪一种类型
再来复习一下typeof的用法:
// 基本类型
typeof 123; //number
typeof "123"; //string
typeof true; //boolean
typeof undefined; //undefined
typeof null; //object
let s = Symbol;
typeof s; //symbol
// 引用类型
typeof [1,2,3]; //object
typeof {}; //object
typeof function(){}; //function
typeof Array; //function Array类型的构造函数
typeof Object; //function Object类型的构造函数
typeof Symbol; //function Symbol类型的构造函数
typeof Number; //function Number类型的构造函数
typeof String; //function String类型的构造函数
typeof Boolean; //function Boolean类型的构造函数
复制代码
两种简单,但是不是十分准确的方法
var obj = [4,67,23];
obj instanceof Array; //return true
obj.constructor == Array; // return true
复制代码
为什么不准确?
首先来复习一下instanceof用法
- 判断一个实例是否属于某种类型
function Foo(name) {
this.name = name;
}
var f = new Foo('zhangsan');
console.log(f instanceof Foo); //true
console.log(f instanceof Object); //true
复制代码
- 判断一个实例是否属于它的父类型
function Person() {};
function Student() {};
var p = new Person();
Student.prototype = p;
var s = new Student();
console.log(s instanceof Student); //true
console.log(s instanceof Person); //true
记忆:
A instanceof C 等价于 A 是否是 C子类,或者后代?
复制代码
instanceof 判断逻辑?
判断逻辑翻译成js代码如下:
_instanceof(f, Foo);
function _instanceof(L, R) {
var R = o.prototype;
var L = L.__proto__;
while( true) {
if(L == null) {
return false;
}
if(L == R) {
return true;
}
L = L.__proto__;
}
}
复制代码
instanceof 不准确的原因?
代码如下:
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var arr = [1,2,3];
xArray = window.frames[0].Array; //iframe中的构造函数
var arrx = new xArray(4,5,6);
console.log(arrx instanceof Array); //false
console.log(arrx.constructor == Array);// false
console.log(Array.prototype == xArray.prototype); //false
console.log(arr instanceof xArray); //false
console.log(arrx.constructor === Array);// false
console.log(arr.constructor === Array);// true
console.log(arrx.constructor === xArray);// true
console.log(Array.isArray(arrx)); //true
复制代码
解释:红宝书,p88
instanceof操作符的问题在于,它假定只有一个全局环境。如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。
如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
constructor 不准确的原因?
因为constructor可以被重写,所以不能确保一定是数组
example:
var str = 'abc';
str.constructor = Array;
str.constructor === Array // return true
复制代码
而很明显str不是数组。
而且constructor和instanceof存在同样问题,不同执行环境下,constructor判断不正确问题。
方法3 isArray()
最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的,这个方法的用法如下。
if(Array.isArray(value)){
return true;
}
复制代码
方法4 Object.prototype.toString
如果在尚未实现isArray方法的浏览器中准确监测数组,我们需要用到Object.prototype.toString方法来判断,每一个继承自Object的对象都拥有toString的方法。
if(!Array.isArray){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==='[object Array]'
}
}
复制代码
自己可以封装一个获取变量类型的函数
function getType(obj) {
return Object.prototype.toString.call(obj).slice(8,-1);
}
var a = [1,2,3];
console.log(getType(a)); //Array
var b = function(){};
console.log(getType(b)); //Function
复制代码
参考文章
JavaScript instanceof 运算符深入剖析 javascript 判断变量是否是数组(Array)