准备工作
typeof
typeof
操作符返回一个字符串,表示未经计算的操作数的类型。
下表总结了typeof
可能的返回值。有关类型和原始值的更多信息,可查看 JavaScript数据结构 页面。
类型 | 结果 |
---|---|
Undefined | "undefined" |
Null |
"object" (见下文) |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Symbol (ECMAScript 6 新增) | "symbol" |
宿主对象(由JS环境提供) | Implementation-dependent |
函数对象([[Call]] 在ECMA-262条款中实现了) | "function" |
任何其他对象 | "object" |
call
call()
方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
let obj ={};
console.log(obj.toString());//[object Object]
console.log(obj.toString.call(new String));//[object String]
console.log(obj.toString.call(new Date));//[object Date]
console.log(obj.toString.call(new Array));//[object Array]
console.log(obj.toString.call(new Number));//[object Number]
console.log(obj.toString.call(Function));//[object Function]
console.log(obj.toString.call(Math));//[object Math]
console.log(obj.toString.call(undefined));//[object Undefined]
console.log(obj.toString.call(null));//[object Null]
null
最特殊的null
,下面是MDN的解释:
在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null的类型标签也成为了 0,typeof null就错误的返回了"object"。(曾经看过某易的大神说就是这么设计的,不是故意错误返回object
,null
不是基础类型,因为typeof null === 'object'
)
源码解析
本文中,jQuery才用的是3.4.1版本。一般情况下判断数据类型,采用typeof
即可,为啥JQuery还进行了自己的封装呢,很说明存在漏洞。我们先从jQuery判断对象入手。
var isFunction = function isFunction( obj ) {
// Support: Chrome <=57, Firefox <=52
// In some browsers, typeof returns "function" for HTML <object> elements
// (i.e., `typeof document.createElement( "object" ) === "function"`).
// We don't want to classify *any* DOM node as a function.
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
结合上面的typeof
的知识,已经能判断出function
,为什么还 多余 的判断typeof obj.nodeType !== "number"
。注释已经给出答案,在某些古老的浏览器中,typeof document.body.childNodes // function
。
还有MDN上也指出,对正则表达式字面量的类型判断在某些浏览器中不符合标准
typeof /s/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1
typeof /s/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1
所以通过typeof
判断数据类型在古老的浏览器中是极为不靠谱的,所以在jquery的isFunction的判断中额外添加了判断 检测对象是否为dom对象。
jQuery 判断类型
有了上面的基础typeof
和call
,再看下面源码,结合注释基本就什么阻碍了。
var class2type = {};//定义一个空对象
var toString = class2type.toString;
function toType( obj ) {
if ( obj == null ) {//null 特殊处理
return obj + "";
}
// Support: Android <=2.3 only (functionish RegExp)
//一个三元运算符
// 因为上文提到存在typeof /s/ 为 function的情况,所以需要toString详细判断
//对于判断不出的数据类型默认为object
// 通过上面typeof对类型判断的表格,判断非object function还是很可靠的,所以直接用原生方法
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call( obj ) ] || "object" :
typeof obj;
}
// Populate the class2type map
//把所以类型的字符串分割成字符串数组,遍历后以[object object]为key保存在class2type对象中(如下图)
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
function( i, name ) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
} );
class2type
总结
通过用toString方法可以判断出Boolean、Number、 String、 Function、 Array、 Date、 RegExp、 Object、 Error、 Symbol、undefined 这些数据类型。并不能判断出null,所以要采用上面的方式。
网友评论