likes
comments
collection
share

前端面试(六):快速检测JS变量类型

作者站长头像
站长
· 阅读数 26

前言

JavaScript中有基本类型的变量,也有引用类型的变量,复杂的变量还涉及到继承等等,我们如何快速知道一个变量究竟是什么类型呢?

在面试中,我就被深深追问过这个问题,typeof?instanceof?prototype?这样判断是不是太慢了?有没有更直接的?面试官连连摇头,我的心态也逐渐崩溃。

基本类型的判定方法

JavaScript的基本数据类型有:null,undefined,string,number,boolean,symbol,bigint

typeof 是判断基本类型的好方法。

typeof

typeof A可以返回一个字符串,表明变量的类型。

如下所示,如果变量是基本数据类型的话,可以返回出变量的具体类型。但如果变量是引用类型比如object、function的话,只能返回这两个比较泛泛的类型,如果想知道具体是什么类型的对象/方法,是不支持的。

var nul = null;
var und = undefined;
var str = 'hello world';
var num = 1;
var boo = true;
var sym = Symbol('flag');
var big = 520n;
var obj = new Object();
var fun = function(){}
console.log(typeof nul); // null
console.log(typeof und); // undefined
console.log(typeof str); // string
console.log(typeof num); // number
console.log(typeof boo); // boolean
console.log(typeof sym); // symbol
console.log(typeof big); // bigint
console.log(typeof obj); // object
console.log(typeof fun); // function

引用类型

instanceof

这里代码参考JS之instanceof详解

instanceof 可以判断某个构造函数是不是在某个实例对象的原型链上,从而判断对象是不是某个类型/子类的实例。

object instanceof constructor,用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

// 定义构造函数
function C () {}
function D () {}
// 实例化一个 o 对象
var o = new C()
// true,true --> C.prototype 在 o 的原型链上
console.log(o instanceof C, o.__proto__ === C.prototype, '此时 o 的 __proto__:', o.__proto__, '此时 C 的 prototype:', C.prototype)
// false,false --> D.prototype 不在 o 的原型链上
console.log(o instanceof D, o.__proto__ === D.prototype)
// true true --> Object.prototype 在 o 的原型链上
console.log(o instanceof Object, o.__proto__.__proto__ === Object.prototype)
// 这时我们修改构造函数 C 的原型为一个空对象
C.prototype = {}
// 实例化一个 o2 对象
var o2 = new C()
// true --> C.prototype 在 o2 的原型链上
console.log(o2 instanceof C)
// false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上.
console.log(o instanceof C, '此时 o 的 __proto__:', o.__proto__, '此时 C 的 prototype:', C.prototype)
console.log('此时 D 的 prototype:', D.prototype);
// 继承
D.prototype = new C()
console.log('此时 D 的 prototype:', D.prototype);
var o3 = new D()
// true, true --> 因为 o3 是 构造函数 D new 出来的实例对象,所以 D.prototype 一定在 o3 的原型链上
console.log(o3 instanceof D, o3.__proto__ === D.prototype)
// true --> 因为 C.prototype 现在在 o3 的原型链上
console.log(o3 instanceof C)
// true,true --> 上面的结果为什么为 true 呢,看如下代码,D.prototype 是 构造函数 C new 出来的实例对象,所以 C.prototype 一定在 D.prototype 的原型链上
console.log(o3.__proto__ === D.prototype, D.prototype.__proto__ === C.prototype);
// true 相当于如下代码
console.log(o3.__proto__.__proto__ === C.prototype);

终极方法

Object.prototype.toString.call()

Object.prototype.toString.call() 既可以判断基本数据类型,又可以判断引用类型(比如一些内置对象),还可以很快出结果。 深入理解Object.prototype.toString.call()方法

一般来说,一些基本数据类型和引用类型都有自己的toString()方法,在直接调用时,往往会找到原型链上离得最近的toString()方法去调用。 Object.protoype.toString()调用这个原始toString方法可以返回类似于 [object classname] 的字符串。其规则如下:

前端面试(六):快速检测JS变量类型

为了直接得到变量类型,我们需要让变量能够直接调用这个原始方法。Object.prototype.toString.call(A)用call将this绑定在了变量A上,就可以实现这一目的。


// Object.prototype.toString.call()
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(undefined));  // [object Undefined]
console.log(Object.prototype.toString.call("hello world")); // [object String]
console.log(Object.prototype.toString.call(12321)); // [object Number]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call(Symbol('flag'))); // [object Symbol]
console.log(Object.prototype.toString.call(520n)); // [object BigInt]
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call(function(){})); // [object Function]
console.log(Object.prototype.toString.call(new Array())); // [object Array]
console.log(Object.prototype.toString.call(Boolean())); // [object Boolean]
console.log(Object.prototype.toString.call(new Date())); // [object Date]
console.log(Object.prototype.toString.call(Error())); // [object Error]
console.log(Object.prototype.toString.call(Function())); // [object Function]
console.log(Object.prototype.toString.call(JSON)); // [object JSoN]
console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(Number())); // [object Number]
console.log(Object.prototype.toString.call(Object())); // [object Object]
console.log(Object.prototype.toString.call(RegExp())); // [object RegExp]
console.log(Object.prototype.toString.call(String())); // [object string]

参考文档

  1. JS之instanceof详解
  2. Object.prototype.toString.call (obj) 使用方法以及原理
  3. 讲透Object.prototype.toString.call()
  4. 深入理解Object.prototype.toString.call()方法
转载自:https://juejin.cn/post/7366516215377952818
评论
请登录