【每日一题】 JavaScript数据结构|JavaScript如何判断数据类型?实现一个instanceof
JavaScript判断数据类型的方法大致有四种:typeof、instanceof、constructor、Object.prototype.toString.call()
typeof
console.log(typeof 11); // number
console.log(typeof true); // boolean
console.log(typeof 'bear'); // string
console.log(typeof []); // object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object
// 其中数组、对象、null都会被判断为object
instanceof
- Instanceof 用于判断对象的类型,其运行机制是判断在其原型链能否找到该类型的原型
console.log(11 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('bear' instanceof String); // false
// instanceof 无法判断基本数据类型
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
// instanceof 可以正确判断引用数据类型
如何实现一个instanceof
- instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
function myInstanceof(leftValue, rightValue) {
let proto = Object.getPrototypeOf(leftValue), // 获取对象的原型
prototype = rightValue.prototype; // 获取构造函数的 prototype 对象
// 判断构造函数的 prototype 对象是否在对象的原型链上
// 循环判断对象的原型是否等于类型的原型,直到对象原型为null
while (true) {
if (!proto) return false;
if (proto === prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}
constructor
- constructor本来是原型对象上的属性,指向构造函数。根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor属性的
console.log((11).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('bear').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
function Fn(){};
Fn.prototype = new Array();
var f = new Fn();
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true
// 由于constructor属性是可以变更的,也会导致检测出的结果不正确
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true
console.log((null).constructor) //报错
console.log((undefined).constructor) //报错
// undefined和null没有constructor属性,所以判断时代码可能会报错--这很致命,会导致代码运行不下去,所以只有在确定待判断的值不是undefined和null才能使用
Object.prototype.toString.call()
Object.prototype.toString.call() 使用Object对象的原型方法toString来判断数据类型,是一种较为通用可靠的判断方式
var a = Object.prototype.toString;
console.log(a.call(11)); // [object Number]
console.log(a.call(true)); // [object Boolean]
console.log(a.call('bear')); // [object String]
console.log(a.call([])); // [object Array]
console.log(a.call(function(){})); // [object Function]
console.log(a.call({})); // [object Object]
console.log(a.call(undefined)); // [object Undefined]
console.log(a.call(null)); // [object Null]
// 获取this指向的那个对象的[[Class]]属性的值。
// 计算出三个字符串"[object "、 第一步的操作结果Result(1)、 以及 "]" 连接后的新字符串。
// 返回第二步的操作结果Result(2),也就是类似 [object className] 这种格式字符串。
// [[class]]类属性:对象的类属性(class attribute)是一个字符串,用以表示对象的类型信息。并只有一种间接的方法可以查询到它。默认的toString方法(继承自Object.prototype)返回了如下格式的字符串:[object class]
\