typeof 方法
检测一个变量的类型(并不能判断是否是数组)
typeof是一个运算符,有两种使用方式:typeof(表达式);typeof 变量名,一种是对表达式做运算,一种是对变量名做运算。
typeof 的返回值的类型为字符串,有以下几种:
1、'undefined' —— 未定义的变量或值
2、'boolean' —— 布尔类型的值或变量
3、'string' —— 字符串类型的变量或值
4、'number' —— 数字类型的变量或值
5、'object' —— 对象类型的变量或值,或者 null(这个是 js 历史遗留问题,将 null 作为 object 类型处理)
6、'function' —— 函数类型的变量或值
简单示例:
console.log(typeof a); // 'undefined'
console.log(typeof true); // 'boolean'
console.log(typeof '123'); // 'string'
console.log(typeof 123); // 'number'
console.log(typeof NaN); // 'number'
console.log(typeof null); // 'object'
var obj = new String();
console.log(typeof obj); // 'object'
var fn = function(){};
console.log(typeof fn); // 'function'
console.log(typeof class c{}); // 'function'
typeof 运算符用于判断对象的类型,但是对于一些创建的对象,它都会返回 object,下面看看数组的判断方式。
1、Array.isArray
ES5 新增的方法
const arr = [1, 2, 3, 4, 5];
Array.isArray(arr); // true
instanceof
一般来说,instanceof 关键字,用于判断某个元素是否某对象构造函数实例。(判断右边参数的原型是否在左边参数的原型链上。)
const arr = [1, 2, 3, 4, 5]
arr instanceof Array; // true
3、toString
每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写,会返回 [object type],其中 type 为对象的类型。但当除了 object 类型的对象外,其他类型直接使用 toString 方法,会直接返回内容的字符串,所以我们需要用 call 或者 apply 方法来改变 toString 方法的执行上下文。
let arr = ['hello', 'world'];
arr.toString(); // 'hello world'
Object.prototype.toString.call(arr); // '[object Array]'
一般来说这种方式的判定是各大库的一种 Array.isArray 的代替实现。
例如:polyfill 中就是如此实现:call 方法用来改变 toString 方法的执行上下文。
if (!Array.isArray) {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === '[object Array]'
}
}
这种方法对于所有基本数据类型都可以进行判断,包括 null 和 undefined
Object.prototype.toString.call('yue'); // '[object String]'
Object.prototype.toString.call(1); // '[object Number]'
Object.prototype.toString.call(Symbol(1)); // '[object Symbol]'
Object.prototype.toString.call(null); // '[objectNull]'
Object.prototype.toString.call(undefined); // '[object Undefined]'
Object.prototype.toString.call(function(){}); // '[objectFunction]'
Object.prototype.toString.call({name: 'yue'}); // '[object Object]'
const arr = [1, 2, 3, 4, 5];
Object.prototype.toString.call(arr) === '[object Array]' // true
4、constructor
通过构造函数来判定:
const arr = [1, 2, 3, 4, 5];
arr.constructor === Array; // true
arr.__proto__.constructor === Array; // true
弊端
instanceof 和 constructor 的判定也存在一些弊端,他们判定的数组必须定义在同一个页面,否则就会判定为 false。
如果在 iframe 中的数组判定,就会出错:
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]
// Correctly checking for Array
Array.isArray(arr); // true
// Considered harmful, because doesn't work through iframes
arr instanceof Array; // false
arr.constructor === Array; // false
总结
由以上判定方法可以得出,polyfill 的判定方式是最合理的,也是最具有兼容性的一种判定:利用 toString 判定。