JS中的数据类型判断

2018-01-31  本文已影响40人  风起云涌Hal

一、typeof()

首先看一批操作,我们可以思考下这些操作的结果会是什么:

// 1.
typeof null
typeof undefined
typeof true
typeof 1

// 2.
typeof(new String('123'))
typeof(Number('abc'))       
typeof(new Number(123))

// 3.
typeof []
typeof(Array)
typeof(new Array)

// 4.
typeof function() {}
typeof(Function)
typeof(new Function)

// 5.
typeof {}
typeof Object
typeof new Object()

在浏览器中执行上面的操作后,可以得到如下结果:

// 1.
typeof null // "object"
typeof undefined // "undefined"
typeof true // "boolean"
typeof 1 // "number"

// 2.
typeof(new String('123')) // "object"
typeof(Number('abc')) // "object"
typeof(new Number(123)) // "object"

// 3.
typeof [] // "object"
typeof(Array) // "function"
typeof(new Array) // "object"

// 4.
typeof function() {} // "function"
typeof(Function) // "function"
typeof(new Function) // "function"

// 5.
typeof {} // "object"
typeof Object // "function"
typeof new Object() // "object"

typeof操作符返回一个字符串,指示未经计算的操作数的类型。有部分数据类型比较特殊:

typeof /s/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1
typeof /s/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1
typeof undeclaredVariable === 'undefined';
typeof newLetVariable; let newLetVariable; // ReferenceError
typeof newConstVariable; const newConstVariable = 'hello'; // ReferenceError
typeof document.all === 'undefined';

上述typeof的操作,我们可以发现在很大程度上,typeof无法获取到准确的类型(譬如typeof null === "object"; typeof [] === "object";)。因而我们介绍一种更为通用的判断类型的方式:

二、Object.prototype.toString.call()

我们将上一节中的所有操作替换为Object.prototype.toString.call

// 1.
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(1) // "[object Number]"

// 2.
Object.prototype.toString.call(new String('123')) // "[object String]"
Object.prototype.toString.call(Number('abc')) // "[object Number]"
Object.prototype.toString.call(new Number(123)) // "[object Number]"

// 3.
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(Array) // "[object Function]"
Object.prototype.toString.call(new Array) // "[object Array]"

// 4.
Object.prototype.toString.call(function() {}) // "[object Function]"
Object.prototype.toString.call(Function) // "[object Function]"
Object.prototype.toString.call(new Function) // "[object Function]"

// 5.
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(Object) // "[object Function]"
Object.prototype.toString.call(new Object()) // "[object Object]"

从以上结果我们看到,使用Object.prototype.toString.call方法能够得到更为准确的类型。

三、ES6中Object.prototype.toString.call()的拓展

如果我们定义了一个类,然后实例化这个类,那么这个实例的类型是否应该为这个类呢?如下:

function Person(name) {
    this.name = name;
}
var p = new Person('Hal');

typeof p; // "object"
Object.prototype.toString.call(p); // "[object Object]"

这个与我们想要的结果不大一样,我们希望执行Object.prototype.toString.call(p)时能够获得实际的类型:"[object Person]"。ES6中,提供了一种方式:

Person.prototype[Symbol.toStringTag] = 'Person';

再次执行Object.prototype.toString.call(p)时我们能够获得想要的结果:"[object Person]"。这是因为在该对象上面调用Object.prototype.toString方法时,如果[Symbol.toStringTag]属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。

综上所述,我们判断数据类型时,推荐使用Object.prototype.toString.call()这种方式。

上一篇下一篇

猜你喜欢

热点阅读