热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

超越Jquery_01_isPlainObject分析与重构_javascript技巧

isPlainObject是Jquery1.4后提供的新方法,用于判断对象是否是纯粹的对象(通过{}或者newObject创建的)。
isPlainObject是Jquery1.4后提供的新方法,用于判断对象是否是纯粹的对象(通过 "{}" 或者 "new Object" 创建的)。

使用isPlainObject
  首先我们来了解一下什么叫'纯粹的对象',简单的理解'纯粹的对象'指的就是由Object构造出来的对象。那哪些对象是由Object构造出来的呢。首当其充的肯定是由new Object()所构造出来的对象,注意:在Object后的括号里可没加任何东西。因为Object是所有'类'的根基,因此它有一些特殊的行为,如当调用new Object(3)的时候,会构造一个Number类型的对象。new Object('')会构造一个String类型的对象。然后以{}这种形式定义的对象也属于'纯粹的对象'。'{}'的实质就是new Object(),只是表现形形式不同。好,让我们来看一段代码:

代码如下:


var objStr = new Object('');
alert(objStr.constructor);//String
alert(isPlainObject(objStr));//false
var objNum = new Object(3);
alert(objNum.constructor);//Number
alert(isPlainObject(objNum));//false
function Person(){}
var person = new Person();
alert(isPlainObject(person));//false
var obj01 = new Object();
obj01.name = '笨蛋的座右铭';
alert(isPlainObject(obj01));//true
alert(isPlainObject({name:'笨蛋的座右铭'}));//true


isPlainObject源码分析
以下代码为Jquery中的isPlainObject的完整版本,注释已经很详尽了,我就不多说什么了。

代码如下:


var toString = Object.prototype.toString,
hasOwnProperty = Object.prototype.hasOwnProperty;
function isPlainObject( obj ) {
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
//Make sure that DOM nodes and window objects don't pass through, as well
//windows objects:toString.call(window):IE [object Object] FF [object Window] chrome [window global] safari [object DOMWindow]
//DOM nodes:toString.call(#p01):IE [object Object] FF [object Window] chrome [object global] safari [object DOMWindow]
//结论:obj.nodeType || obj.setInterval主要是针对于IE浏览器进行判断
//注:history,location,navigator,screen的setInterval为undefined
if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
return false;
}
// Not own constructor property must be Object
// 除去自定义对象和内置对象的判断,如function Person(){} var p = new Person();String,Number
if ( obj.constructor //有constructor属性
&& !hasOwnProperty.call(obj, "constructor") //并且constructor这个属性必须是在原型链中进行定义的
&& !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")//并且原型中有isPrototypeOf方法,一般只有Object的原型中才有这个方法
) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
//针对于复杂类结构,如有继承...
/*
//一个简单的测试
function Animal(name){
}
function Person(name,age){
Animal.call(this,name);
this.age =age;
}
var p = new Person('jxl',20);
for(key in p){
alert(hasOwnProperty.call( p, key ))//true , false
}
*/
var key;
for ( key in obj ) {}
return key === undefined || hasOwnProperty.call( obj, key );
}


提出问题
个人感觉这个实现比较复杂,而且有BUG。
简单的BUG,history,location,navigator,screen可以顺序通过 isPlainObject的检测返回true.
来看一个我的解决方案(修改BUG,简化):

代码如下:


function isPlainObject(obj){
if(obj&&Object.prototype.toString.call(obj)==="[object Object]"&&obj.cOnstructor===Object &&!hasOwnProperty.call(obj, "constructor")){
var key;
for ( key in obj ) {}
return key === undefined || hasOwnProperty.call( obj, key );
}
return false;
}


还有BUG,而且是一个无解的BUG:

代码如下:


function m(){};
m.prototype.cOnstructor=Object; //必杀
obj=new m;
alert(isPlainObject(obj)); //true


再来一个同理的:

代码如下:


function m(){};
m.prototype = {};
obj=new m;
alert(isPlainObject(obj)); //true


这个答案是无解的!

解答无解
本以为这个问题很好解决,结果深入后,发现这是一个无解的问题。原因如下:

代码如下:


function Person(){};
Person.prototype.cOnstructor=Object;
var person=new Person;


让我们来看一下person现在的状态:

person和其构造函数Person唯一的联系就是其prototype链中的constructor属性。而在我们判断是否为'纯粹的对象'主要是依据对象实例的constructor进行的。如果我们将其指向Object,正如图中看到的那样,那么person和Person在代码上就没有关系了。也正是因为这一点,让类型的判断出现了问题。
推荐阅读
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • ECMA262规定typeof操作符的返回值和instanceof的使用方法
    本文介绍了ECMA262规定的typeof操作符对不同类型的变量的返回值,以及instanceof操作符的使用方法。同时还提到了在不同浏览器中对正则表达式应用typeof操作符的返回值的差异。 ... [详细]
  • 文章目录简介HTTP请求过程HTTP状态码含义HTTP头部信息Cookie状态管理HTTP请求方式简介HTTP协议(超文本传输协议)是用于从WWW服务 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 使用chrome编辑器实现网页截图功能的方法
    本文介绍了在chrome浏览器中使用编辑器实现网页截图功能的方法。通过在地址栏中输入特定命令,打开控制台并调用命令面板,用户可以方便地进行网页截图操作。 ... [详细]
  • 如何压缩网站页面以减少页面加载时间
    本文介绍了影响网站打开时间的两个因素,即网页加载速度和网站页面大小。重点讲解了如何通过压缩网站页面来减少页面加载时间。具体包括图片压缩、Javascript压缩、CSS压缩和HTML压缩等方法,并推荐了相应的压缩工具。此外,还提到了一款Google Chrome插件——网页加载速度分析工具Speed Tracer。 ... [详细]
  • 本文整理了常用的CSS属性及用法,包括背景属性、边框属性、尺寸属性、可伸缩框属性、字体属性和文本属性等,方便开发者查阅和使用。 ... [详细]
  • CSS|网格-行-结束属性原文:https://www.gee ... [详细]
  • css元素可拖动,如何使用CSS禁止元素拖拽?
    一、用户行为三剑客以下3个CSS属性:user-select属性可以设置是否允许用户选择页面中的图文内容;user-modify属性可以设置是否允许输入 ... [详细]
  • css,背景,位置,y,background, ... [详细]
author-avatar
手机用户2502935287_564
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有