关于js判断数据类型,会,但好像又不是完全会,在面试中总是被一些奇怪的问题搞得很狼狈。
但是有了这篇文章,妈妈再也不用担心面试被问到数据类型的问题了。
First blood
面试官:可以说一下js判断数据类型的方法吗?
我:判断基本数据类型可以用typeof,判断复杂数据类型可以用instanceof,它主要通过判断前者否为后者的实例对象来实现的。同时也可以使用Object.prototype.toString.call()方法和构造函数constructor来判断数据类型。
面试官:哦?那你知道instanceof是怎么判断前者是否为后者的实例化对象的吗,可以自己实现出来吗。
我:(自己写?请问您礼貌吗,还好我有所准备,根本没在怕的)
首先,a instanceof A ,主要是通过在a的原型链上一层一层去找,如果能找到A.prototype,就说明a是A的实例化对象。如果找到头都没有找到A.prototype,那就说明a不是A的实例化对象。那怎么能知道找到头呢?因为所有对象从原型链向上找,最后一个一定是null,倒数第二个是Object。所以我们可以说所有的对象都是Object的实例化对象。
如果不够清楚我们可以举个例子,例如我们创建一个数组的对象,我们看一下它的原型链的情况:
let arr = new Array()
arr.__proto__ === Array.prototype // true
arr.__proto__.__proto__ === Object.prototype // true
arr.__proto__.__proto__.__proto__ === null // true
有了这个思路我们就可以手动自己写一个instanceof方法了。
function myInstanceof(left,right){
if(typeof left !== 'object' || left === null){
return false;
}
let leftProto = left.__proto__
let rightProto = right.prototype
while(true){
if(leftProto === null){
return false
}
if(leftProto === rightProto){
return true
}
leftProto = leftProto.__proto__
}
}
Double kill
面试官:说得不错,那你刚才说的Object.prototype.toString.call()是怎么做到能判断数据类型的呢?其中的prototype和call都是用来做什么的。
我:(够刁钻,但是我依旧可以的)
首先说一下为什么要以Object.prototype的这种写法,因为对于一些像数组,字符串类型的,它们已经重写了toString()方法
console.log('123'.toString()); // 123
console.log([1,2,3].toString()); //1,2,3
所以我们才使用Object.prototype.toString()这种保险的方式来写。而这个方法会根据this来返回一个像'[object xxx]'这种形式的字符串,后面这个xxx就是this对象的类型。如果直接调用,那么就是Object的类型,返回的值也就是'[object Object]'
如果想要判断其他类型的对象,我们只要改变了调用这个方法的this对象,就可以获得改变后对象的类型了,那如何改变this的指向呢?我们可以在方法的后面加上一个call方法。
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call({}) ; // [object Object]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Triple kill
面试官:答的不错,那我给你出几个题做吧。都是和数据类型相关的,做一下试试
console.log(true + 0);
console.log(true + 'abc');
console.log(true+true);
console.log(true+false);
console.log(null + 1);
console.log(undefined + 1);
console.log(undefined + '123');
console.log('1'>true);
console.log('3'>true);
console.log(1+'2'+false);
console.log('2' + ['arr',1]);
console.log(NaN == NaN);
console.log(null == undefined);
console.log(null === undefined);
console.log(1 == true);
console.log(0 === false);
var p1 = {
name: 'lisi',
age: 20
}
var p2 = {
toString(){
return 'name:wangwu,age:18'
}
}
console.log('嘻嘻' + p1);
console.log('哈哈' + p2);
我:👴不做