整理数据类型检测。附加几个jquery中的检测方法
复习js中数据类型检测的四种方法
- typeof
- instanceof
- constructor
- Object.prototype.toString.call
typeof
最常用的方法,虽然不准确,对付一般情况也是够用
- 检测数据类型的 逻辑运算符
- 返回结果都是 字符串
- 返回结果有:
"string"
、"number"
、"boolean"
、"undefined"
、"symbol"
"object"
、"function"
通过返回的字符串就能看出 typeof 的局限性,有几个不能:
- 不能检测null,typeof null === 'object'
- 不能区分正则、时间等对象
- 不能检测array
自我检测: typeof typeof [] 的值是什么。答:"string"
instanceof
检测某个实例是不是这个类
底层机制:所有出现在其原型链上的类
由于这个机制会出现两个问题。1.判断出的对象不一定是真的对象。2.原型链可以更改,类型不能完全相信。看下面两个例子
console.log([] instanceof Array) // true
console.log([] instanceof Object) // true
function Fn(){}
Fn.prototype = Array.prototype
console.log((new Fn()) instanceof Array) // true
不支持基本类型字面量判断
console.log(12 instanceof Number) // false
console.log(new Number(12) instanceof Number) // true
constructor
原理:constructor 指向构造函数
与 instanceof 很像,做一下对比。
\ | 遍历整个原型链 | 手动更改 | 可靠 | 机制 |
---|---|---|---|---|
instanceof | √ | √ | x | 查找原型链 |
constructor | x | √ | x | 属性访问 |
Object.prototype.toString (最可靠的方法)
原理:利用 Object.prototype.toString 上的特殊性。注意不是所有 toString 方法都行!!!
xxx.prototype.toString 方法总结
- 除undefined、null外的基本类型:转化为字符串
- undefined与null是不能属性查找的,不能调取toString
- Array、RegExp、Function等内置类:转化为字符串
- Object: 当前实例所属类的信息 [object Xxxx]
jquery数据类型检测简化版,附加几个常用检测方法
$.type
jquery 源码中有个 toType 方法,其实就是 $.type
类型判断流程
- 核心判断
- 判断 null、undefined
- 基础类型。调用 typeof
- 引用类型。调用 Object.prototype.toString
- 骚操作
- 创建一个例如
{[object Array]: "array"}
的对象。方便"[object Array]"
直接调取"array"
代码如下:
var class2type = {};
var toString = Object.prototype.toString;
// 创建一个例如 {[object Array]: "array"} 的对象
"Boolean Number String Function Array Date RegExp Object Error Symbol".split(" ").forEach(function anonymous(item) {
class2type["[object " + item + "]"] = item.toLowerCase();
});
function toType(obj) {
// 首先判断 null、undefined
if (obj == null) {
return obj + ""; // 返回 "null"、"undefined"
}
// 如果是引用类型:调用 toString 返回 class2type 中对应的类型
// 如果是基本类型:返回 typeof 的结果
return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" :
typeof obj;
}
$.isWindow
核心:利用 window === window.window
function isWindow(obj) {
return obj != null && obj === obj.window;
};
$.isPlainObject
检测是否是纯粹对象
- 核心判断
- Object.prototype.toString 直接过滤掉包括 array、function 在内的所有数据类型
- 判断原型
- 特殊情况:没有原型,返回true
- 解释:由 Object.create(null) 创建的对象没有原型
- 有原型
- 原型上有 constructor,并且 constructor 是 Object,返回true
- 否则,返回false
- 特殊情况:没有原型,返回true
function isPlainObject(obj) {
var proto, Ctor;
// 过滤掉包括 array、function 在内的所有数据类型
if (!obj || Object.prototype.toString.call(obj) !== "[object Object]") {
return false;
}
// 获取当前对象的原型
proto = Object.getPrototypeOf(obj);
// 特殊情况 Object.create(null)
if (!proto) {
return true;
}
// 获取 constructor
Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
// 判断 constructor 是 Object
return typeof Ctor === "function" && Function.prototype.toString.call(Ctor) === Function.prototype.toString.call(Object);
};
$.isEmptyObject
是否是空对象
核心:循环遍历每一项,看是否是空
function isEmptyObject(obj) {
var name;
for (name in obj) {
return false;
}
return true;
};
$.isArrayLike
是否为数组或者类数组
- 核心判断
- 判断真数组
- toType
- 判断类数组
- 判断是否有 length
- 排除 function、window
- length 是数字
- 如果length > 0, 类数组存在 length-1 的属性
- 判断是否有 length
- 判断真数组
function isArrayLike(obj) {
// 判断是否有 length
var length = !!obj && "length" in obj && obj.length,
type = toType(obj);
// 排除 function、window
if (isFunction(obj) || isWindow(obj)) {
return false;
}
// 判断真数组; length 是数字; 如果length > 0, 类数组存在 length-1 的属性
return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
};