超越Jquery_01_isPlainObject分析與重構(gòu)
isPlainObject是Jquery1.4后提供的新方法,用于判斷對象是否是純粹的對象(通過 "{}" 或者 "new Object" 創(chuàng)建的)。
使用isPlainObject
首先我們來了解一下什么叫'純粹的對象',簡單的理解'純粹的對象'指的就是由Object構(gòu)造出來的對象。那哪些對象是由Object構(gòu)造出來的呢。首當(dāng)其充的肯定是由new Object()所構(gòu)造出來的對象,注意:在Object后的括號里可沒加任何東西。因為Object是所有'類'的根基,因此它有一些特殊的行為,如當(dāng)調(diào)用new Object(3)的時候,會構(gòu)造一個Number類型的對象。new Object('')會構(gòu)造一個String類型的對象。然后以{}這種形式定義的對象也屬于'純粹的對象'。'{}'的實質(zhì)就是new Object(),只是表現(xiàn)形形式不同。好,讓我們來看一段代碼:
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的完整版本,注釋已經(jīng)很詳盡了,我就不多說什么了。
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(#div01):IE [object Object] FF [object Window] chrome [object global] safari [object DOMWindow]
//結(jié)論: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
// 除去自定義對象和內(nèi)置對象的判斷,如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.
//針對于復(fù)雜類結(jié)構(gòu),如有繼承...
/*
//一個簡單的測試
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 );
}
提出問題
個人感覺這個實現(xiàn)比較復(fù)雜,而且有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
這個答案是無解的!
解答無解
本以為這個問題很好解決,結(jié)果深入后,發(fā)現(xiàn)這是一個無解的問題。原因如下:
function Person(){};
Person.prototype.constructor=Object;
var person=new Person;
讓我們來看一下person現(xiàn)在的狀態(tài):

person和其構(gòu)造函數(shù)Person唯一的聯(lián)系就是其prototype鏈中的constructor屬性。而在我們判斷是否為'純粹的對象'主要是依據(jù)對象實例的constructor進行的。如果我們將其指向Object,正如圖中看到的那樣,那么person和Person在代碼上就沒有關(guān)系了。也正是因為這一點,讓類型的判斷出現(xiàn)了問題。
相關(guān)文章
webuploader分片上傳的實現(xiàn)代碼(前后端分離)
這篇文章主要介紹了webuploader分片上傳的實現(xiàn)代碼(前后端分離),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09layui table 復(fù)選框跳頁后再回來保持原來選中的狀態(tài)示例
今天小編就為大家分享一篇layui table 復(fù)選框跳頁后再回來保持原來選中的狀態(tài)示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10js實現(xiàn)Select頭像選擇實時預(yù)覽代碼
這篇文章主要介紹了js實現(xiàn)Select頭像選擇實時預(yù)覽代碼,涉及javascript動態(tài)遍歷及設(shè)置select選項的技巧,非常簡單實用,需要的朋友可以參考下2015-08-08JavaScript數(shù)據(jù)結(jié)構(gòu)中串的表示與應(yīng)用實例
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)中串的表示與應(yīng)用,結(jié)合實例形式簡單分析了基于javascript順序操作實現(xiàn)串結(jié)構(gòu)與串的拼接操作相關(guān)技巧,需要的朋友可以參考下2017-04-04