Javascript 中的数据类型判断
typeof
我们都使用 typeof 是用来判断数据类型的命令, 在常规的场景中足以应付数据类型判断的需求:
1 | var obj = { |
由结果可知typeof可以测试出number、string、boolean、undefined及function,而对于null及数组、对象,typeof均检测出为object,不能进一步判断它们的类型。
所以一般来说, typeof 会使用在比较简单的场景, 比如你几乎可以确定数据是哪一类数据然后稍微加以区分的时候.举个简单的例子来说明情况:
instanceof
instanceof 其实适合用于判断自定义的类实例对象, 而不是用来判断原生的数据类型, 举个例子:
1 | // a.html |
1 | // main.html |
是什么原因导致上面的结果呢? 其实 iframe 之间不会共享原型链, 因为他们有独立的执行环境, 所以 frame a 中的数组 a 不会是本执行环境的实例对象. 通过特性嗅探同样不靠谱, 像通过 contructor
Sort, slice 等等的特有的数组(或者其他数据类型)方法或属性, 万一对象中也有 sort, slice 属性, 就会发生误判. 所以最靠谱的方法是使用 Object.prototype.toString 方法.
Object.prototype.toString
在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。
但是它不能检测非原生构造函数的构造函数名。
1 | function foo(){}; |
Object.prototype.toString 的原理是当调用的时候, 就取值内部的 [[Class]] 属性值, 然后拼接成 ‘[object ‘ + [[Class]] + ‘]’ 这样的字符串并返回. 然后我们使用 call 方法来获取任何值的数据类型.
constructor
undefined和null没有contructor属性
1 | console.log(bool.constructor === Boolean);// true |
constructor不能判断undefined和null,并且使用它是不安全的,因为contructor的指向是可以改变的
有用的数据类型判断函数
Array.isArray()
用于确定传递的值是否是一个Array。如果对象是Array,则返回true,否则为false。
1 | Array.isArray([1, 2, 3]); |
isNaN()和Number.isNaN
isNaN()函数用来确定一个值是否为 NaN。
注:isNaN函数内包含一些非常有趣的规则;
你也可以使用 ECMAScript 2015 中定义的Number.isNaN()来判断。
与 JavaScript 中其他的值不同, NaN不能通过相等操作符(== 和 ===)来判断 ,因为 NaN == NaN 和 NaN === NaN 都会返回 false。 因此,isNaN 就很有必要了。
1 | isNaN(NaN); // true |
OK, 成功了,看似很完美,但是接着看以下例子
1 | isNaN('A String'); // true |
会发现,很明显不是 NaN 的 value 也被误判成 NaN 了。
这个BUG已经存在了20年,从JavaScript最开始就一直存在。很明显当初的设计者,在设计isNaN()的时候,局限了在 “Not a Number” 这一字面意思上了:只要不是number就会返回 true。
于是 ES6 为了弥补这一BUG(而不是修正,因为isNaN存在时间太长,有可能很多功能都是基于这个BUG之上的)引入了 Number.isNaN().
1 | Number.isNaN(NaN); // true |
没有ES6的情况下,可以采用以下polyfill
1 | if (!Number.isNaN) { |
判断是否是 DOM 元素
在实际项目里面, 有时或许我们需要判断是否是 DOM 元素对象, 那么在判断的时候利用的是 DOM 对象特有的 nodeType 属性:
1 | isElement: function(obj){ |
判断是否是对象
1 | isObject: function(obj){ |
这里的对象是狭义的, 是通常所指的 key-value 型的集合, 或者是 function 函数并且不为 null.
判断是否是 arguments 对象
判断一个对象是不是 arguments 对象可以通过 Object.prototype.toString 来判断, 但是低版本的浏览器不支持, 他们返回的是 [object Object], 所以需要兼容:
1 | isArguments: function(obj){ |
兼容做法原理是通过对象的 hasOwnProperty 方法来判断对象是否拥有 callee 属性从而判断是不是 arguments 对象.
评论加载中