大家好,我是 404not~found ,目前是做前端研发工作。写博客是为了积累,希望大家一起进步!
博客主页:404not~found
面试官:平时怎么判断前端数据类型
一、复习判断数据类型方法
判断数据类型之前,要先明确前端都有哪些数据类型。其实在 JS 中,存在着 7 种原始数据类型
,分别是:boolean
、null
、undefined
、number
、string
、symbol
、bigint
,以及 引用数据类型
: 对象Object
、 数组Array
、函数Function
等等。
1、typeof
// 基础数据类型
typeof 1 // number
typeof '1' // string
typeof true // boolean
typeof BigInt(2) // bigint
typeof Symbol // symbol
typeof undefined // undefined
typeof null // object
// 引用数据类型
typeof [1] // object
typeof { a: 1 } // object
typeof Math.random // function
注意:
typeof 并不能准确的判断数据类型。除 基础数据类型里的 null 和 引用类型里的 数组和对象类型外 都可以使用 typeof 判断出正确的类型
2、Object.prototype.toString.call
每一个继承 Object 的对象都有 toString 方法,toString 方法会返回 [Object type]。
type 为该对象的类型。但当除了 Object 类型的对象外,其他类型直接使用 toString 方法时,会直接返回内容的字符串值,即:[‘a’,‘bc’].toString()会得到 ‘a,bc’。
所以我们需要使用 call 或者 apply 方法来改变 toString 方法的执行上下文。即:Object.prototype.toString.call([‘a’,‘bc’])会得到 “[object Array]”。
// 判断基本数据类型
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(1); // "[object Number]"
Object.prototype.toString.call(Symbol(1)); // "[object Symbol]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(BigInt(2)); // "[object BigInt]"
// 判断引用数据类型
Object.prototype.toString.call(function() {}); // "[object Function]"
Object.prototype.toString.call({ a: 0 }); // "[object Object]"
Object.prototype.toString.call(['a']); // "[object Array]"
注意:
对于所有基本的数据类型都能进行判断,即使是 null 和 undefined 。缺点
:常用于判断浏览器内置对象。不能精准判断自定义对象,对于自定义对象只会返回 [ object Object ]
function addAge (age) {
this.age = age;
}
var fn = new addAge (100);
Object.prototype.toString.call(fn) // [ object Object ]
3、instanceof
(1) instanceof 语法
object instanceof constructor
object
:某个实例对象constructor
:某个构造函数
[1] instanceof Array // true
{a: 1} instanceof Object // true
Math.random instanceof Function // true
(2) instanceof 是怎么判断数据类型的
我们先假设有一个函数A,A有一个实例化对象a,instanceof的判断规则是沿着 a的__proto__和A的prototype两条线去找的,如果两条线能找到同一个引用,即同一个对象,就返回true,如果找到终点还没有重合就返回false.
(3)instanceof能否判断基本数据类型?
class PrimitiveNumber {
// 用来判断是否为该对象的实例时,会调用这个方法。
// 比如,foo instanceof Foo在方法内,实际调用的是Foo[Symbol.hasInstance](foo)
static [Symbol.hasInstance](x) {
return typeof x === 'number'
}
}
console.log(111 instanceof PrimitiveNumber) // true
其实就是自定义 instanceof 的一种方式,将原有的 instanceof 方法重定义,内部改用typeof方法来判断基本数据类型。
(4)总结
优点
:instanceof 可以弥补 Object.prototype.toString.call() 不能判断自定义实例化对象的缺点。
缺点
:instanceof 重写前 只能用来判断对象类型,原始类型不可以。并且所有对象类型 instanceof Object 都是 true 。对象类型包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function
new Date instanceof Object; // true
console.log instanceof Object; // true
二、简单手写 Instanceof
1、主要原理
//实例化对象
var o = new O();
o instanceof O; // true,因为 Object.getPrototypeOf(o) === O.prototype
2、手写具体代码
const myinstanceof = (a, b) => {
// 如果是基本数据类型,直接false
if (typeof a !== "object" || a === null) {
return false;
}
// 获取实例
let proto = Object.getPrototypeOf(a);
// 循环
while (true) {
if (proto == null) return false; // 没找到
if (proto == b.prototype) return true; // 找到了
proto = Object.getPrototypeOf(proto); // 顺着原型链查找
}
};
console.log(myinstanceof("111", String)); //false
console.log(myinstanceof(new String("111"), String)); //true