isPlainObject函数用于判断传入的对象是否为纯粹的JavaScript对象。具体实现如下:
超越Jquery_01_isPlainObject分析与重构
1. isPlainObject函数分析
isPlainObject函数用于判断传入的对象是否为纯粹的JavaScript对象。具体实现如下:
function isPlainObject(obj) {
var proto, Ctor;
// 剔除null和非对象类型
if (!obj || {}.toString.call(obj) !== "[object Object]") {
return false;
}
proto = Object.getPrototypeOf(obj);
// 没有原型的对象为纯粹的JavaScript对象
if (!proto) {
return true;
}
// 构造函数的原型为Object的实例
Ctor = {}.hasOwnProperty.call(proto, "constructor") && proto.constructor;
return typeof Ctor === "function" && {}.toString.call(Ctor) === {}.toString.call(Object);
}
- 首先判断传参是否为null或者非对象类型,如果是则返回false;
- 然后获取对象的原型对象。
- 没有原型对象的是普通对象(遵循ECMAScript规范),将其视为纯粹对象;
- 通过对象原型判断对象是否通过自定义构造函数生成,如果是则从构造函数原型上查询是否存在Object构造函数,此时这个对象就被视为纯粹JS对象返回true。
2. isPlainObject函数存在的问题
虽然isPlainObject函数能够比较准确地判断传入的对象是否为纯粹JavaScript对象,但是它并没有完美的解决问题:
- 不支持对空对象进行判断
- 对于DOM节点和window对象也会认为其是普通对象
- 还有通过自定义函数生成的对象,如果该函数的原型链上存在Object构造函数,也会被识别为纯粹JavaScript对象,但并非如此。
3. isPlainObject函数重构
下面的代码能够对isPlainObject函数进行完美的重构:
function isPlainObject(obj) {
// 判断是否为对象类型
if (!obj || typeof obj !== 'object' || obj.nodeType || obj.window === obj) {
return false;
}
// 是否拥有Object原型链上的isPrototypeOf属性
if (obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf')) {
return false;
}
return true;
}
- 首先,判断是否为非null的对象类型或者非window的全局对象;
- 如果是DOM节点或全局window对象,则返回false;
- 如果是自定义构造函数生成的对象,则无法通过Object.prototype去验证其是否具有isPrototypeOf属性,也返回false;
- 如果存在isPrototypeOf属性,则一定为纯粹对象。
4. 示例说明
例如,在以下的情况下,isPlainObject函数就会存在不准确的情况:
// 定义一个自定义构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 调用自定义构造函数创建对象
var person1 = new Person('张三', 18);
var isPureObject1 = $.isPlainObject(person1); // 这里将被识别为纯粹对象,因为Person的原型链上存在Object构造函数
// 如下的情况则不会被题识别为纯粹对象,因为obj定义即为空对象
var obj = {};
var isPureObject2 = $.isPlainObject(obj); // 这里也会被误认为不是纯粹对象。
最终,通过isPlainObject函数重构,能够避免以上两种情况的误判。
沃梦达教程
本文标题为:超越Jquery_01_isPlainObject分析与重构
猜你喜欢
- ubuntu 更换apache网站根目录/var/www/html及端口 2023-10-25
- 通过构造AJAX参数实现表单元素JSON相互转换 2022-12-28
- JavaScript实现弹出模态窗体并接受传值的方法 2023-11-30
- HTML5全屏页面滚动个人简历模板 2023-10-27
- Vue3父传子props(组件之间通信) 2023-10-08
- vue父子组件传值不能实时更新的解决方法 2023-07-09
- 不要小看注释掉的JS 引起的安全问题 2023-11-30
- javascript实现的HashMap类代码 2023-12-01
- mint-ui如何自定义messageBox样式 2023-07-10
- ajax异步加载图片实例分析 2022-12-15