JavaScript类型检测优缺点比较

JavaScript 类型检测

​ JavaScript有四种类型检测(typeof,instanceof,constructor,Object.prototype.toString.call()),它们都有自己的特点。平时使用时我么要注意一些坑。

​ 如果是感觉只想学习一个完善的类型检测的方法的同学,建议直接Object.prototype.toString.call()

数组检测 isArray()

​ 这个比较特殊,因为面试可能会问数组的检测方法,我们理应学一下。

描述

Array.isArray() 用于确定传递的值是否是一个 Array

语法

Array.isArray(obj)

使用例

Array.isArray([1, 2, 3]);  
// true
Array.isArray({foo: 123}); 
// false
Array.isArray("foobar");   
// false
Array.isArray(undefined);  
// false

内部实现

因为IE8不支持此方法,如果有面试官问你怎么实现,就用下面方式顶回去。

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

typeof

描述

**typeof**操作符返回一个字符串,表示未经计算的操作数的类型。

语法

typeof num
typeof (num)

​ 注意,typeof并不是JavaScript内置函数、对象,而是一个运算符。

使用例

console.log(typeof undefined) // "undefined"
console.log(typeof null)//"object"

console.log(typeof [])//"object"
console.log(typeof "")//"string"
console.log(typeof 1)//"number"
console.log(typeof (_=>{}))//"function"
console.log(typeof Symbol)//"function"
console.log(typeof Symbol())//"Symbol"
class MyClass{}
console.log(typeof new MyClass())//"object"

​ 我们能直观看到typeof的不足之处!比如,我们无法检测数组类型、无法检测自定义的类。所以我们在项目中应当慎用typeof

instanceof

描述

**instanceof**运算符用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置。

语法

console.log(Array instanceof Object)//true

instanceof是一个二元运算符,两边必须是对象,如A instanceof B将会在B原型链中检查是否存在A,如果存在返回true,否则返回false

​ 注意:1 instanceof Number是错误的语法,因为1并不是对象。

使用例

console.log([1,2,3] instanceof Array)//true
console.log(new Number(0) instanceof Number)//true
console.log(new Number(0) instanceof Object)//true
console.log((_=>{}) instanceof Function)//true
class A{}
class B extends A{}
let a = new A()
let b = new B()
console.log(a instanceof B)//false
console.log(b instanceof A)//true

​ 通过上面代码,我们也能发现一些问题,我们的Number可以匹配Number,同时也可以匹配Object。我们知道原理,因为所有对象原型链的终点都是Object

​ 所以,我们在使用instanceof检测类型时,应当避免在选择结构开头放上num instanceof Object这样的语句。

constructor

描述

​ 返回创建实例对象的 Object 构造函数的引用。*注意,此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。*所有对象都会从它的原型上继承一个 constructor 属性。

语法

obj.prototype.constructor;
obj.constructor;

使用例

var o = {};
o.constructor === Object; // true

var o = new Object;
o.constructor === Object; // true

var a = [];
a.constructor === Array; // true

var a = new Array;
a.constructor === Array // true

var n = new Number(3);
n.constructor === Number; // true
class A {}
class B extends A { }
let a: A = new A();
let b: B = new B();
console.log(a.constructor === A)//true
console.log(b.constructor === B)//true
console.log(b.constructor === A)//false

​ 是的,我们貌似可以用constructor来检测类型了,但是有没有缺点和漏洞呢?您好,有的!举个例子:

function MyArray(){}
MyArray.prototype = new Array()
let myarr = new MyArray()
console.log(myarr.constructor === MyArray)//false
console.log(myarr.constructor === Array)//true

​ 在我们使用不完善的继承、或者修改了prototype而不修改constructor属性,就会造成上面的错误,我们无法匹配我们想要的类型。

​ 但是,只要我们小心的使用constructor属性,还是能给我们带来不少便利。

Object.prototype.toString.call()

描述

toString() 方法返回一个表示该对象的字符串。

​ 每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖toString() 返回 “[object type]”,其中 type 是对象的类型。

语法

Object.prototype.toString()

使用例

let f = Object.prototype.toString;
console.log(f.call("123")) // [object String]
console.log(f.call(null)) // [object Null]
console.log(f.call(undefined)) // [object Undefined]
console.log(f.call(/aaaa/)) // [object RegExp]
class A{}
let a = new A()
function MyArray(){}
MyArray.prototype = new Array()
let myarr = new MyArray()
console.log(f.call(a)) // [object Object]
console.log(f.call(myarr))// [object Object]

​ 缺点还是有点明显,toString只能检测出内置类型,无法检测出自定义类,所以我们应当在项目中,混用Object.prototype.toStringinstanceof

脑瘫码农 纯靠自学 如有错误 望请指正 共同学习 不胜感激

参考

发布了31 篇原创文章 · 获赞 38 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/yhy1315/article/details/100041468
今日推荐