jQuery.isPlainObject方法源碼解析
1.簡述函數(shù)功能:
--[官方描述](http://www.css88.com/jqapi-1.9/jQuery.isPlainObject/):測試一個(gè)對象是否是純粹對象,但是
結(jié)合代碼測試你雌,個(gè)人得出該方法是用于判斷不存在屬性值指向函數(shù)原型的對象或者是存在屬性指向函數(shù)原型但是函數(shù)原型必須是
Object.prototype,請看以下測試代碼能夠驗(yàn)證:
1).什么是純粹對象姐浮?即是通過{}或者new Object()方式創(chuàng)建的對象;
2).a).noPrototype,ownNoPrototype是不具備屬性指向函數(shù)原型的對象为流;
b).literal,hasPrototype攀例,object,ownHasPrototype是具備屬性指向Object.prototype的對象羡亩;
c).ownObject是具備屬性指向自定義函數(shù)ownDef原型的對象,
d).ownConObject是constructor是自身屬性的對象
3).通過以下輸出結(jié)果可以斷定isPlainObject函數(shù)的功能的判斷依據(jù)與對象使用什么方式創(chuàng)建無關(guān)状勤,而是與對象是否沒有屬
性指向原型鞋怀,有屬性指向函數(shù)原型的對象,它的函數(shù)原型是否是Object.prototype有關(guān)系持搜;
測試代碼:
/*Object.create(null)密似,Object.create(Object.prototype),字面量{},內(nèi)置Object()
Object.create內(nèi)部實(shí)現(xiàn)如下:
// 傳入一個(gè)對象葫盼,作為F函數(shù)原型
function create(object) {
function F(){}
F.prototype = object;
return new F();
}
*/
var noPrototype = Object.create(null);
console.log($.isPlainObject(noPrototype)); // true
var literal = {};
console.log($.isPlainObject(literal)); // true
var hasPrototype = Object.create(Object.prototype);
console.log($.isPlainObject(hasPrototype)); // true
var object = new Object();
console.log($.isPlainObject(object)); // true
// 自定義函數(shù)創(chuàng)建對象
function ownDef() {}
var ownObject = new ownDef();
console.log($.isPlainObject(ownObject)); // false
ownDef.prototype.isPrototypeOf = '';
var ownHasPrototype = new ownDef();
console.log($.isPlainObject(ownHasPrototype)); // false
ownDef.prototype.isPropertyOf = 'xxx';
var owntransProtoProper = new ownDef();
console.log($.isPlainObject(owntransProtoProper)); // false
ownDef.prototype = null;
var ownNoPrototype = new ownDef();
console.log($.isPlainObject(ownNoPrototype)); // true
ownDef.prototype = Object.prototype;
var ownHasPrototype = new ownDef();
console.log($.isPlainObject(ownHasPrototype)); // true
function ownConstructor(){
this.cunstructor = 'ownConstructor';
}
var ownConObject = new ownConstructor();
console.log($.isPlainObject(ownConObject)); // true
2.源碼解析:
--整體思路:在js可編程區(qū)域object可能類型太多種了残腌,比如:window(包含BOM對象),DOM對象贫导,js對象(內(nèi)置對象抛猫,自
定義函數(shù)創(chuàng)建對象,字面量,Object.create函數(shù))孩灯,本函數(shù)的流程主要就是如何過濾掉不符合的對象闺金。
代碼片1:
/* a.!obj過濾了undefined和null;
b.jQuery.type(obj) !== "object",過濾了不是內(nèi)置對象創(chuàng)建的對象除了Object()函數(shù)創(chuàng)建的;
c.obj.nodeType,過濾DOM對象,因?yàn)槊總€(gè)DOM對象他的NodeType都存在且不為0;
d.jQuery.isWindow( obj ),過濾掉window對象
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
return false;
}
代碼塊2:
try {
/* 上一步過濾之后就只剩下自定義函數(shù)峰档,new Object()方法败匹,Object.create()方法,三種方式創(chuàng)建的對象讥巡;
結(jié)合以上測試代碼的對象流程圖片分析:
--流程圖可以看出if()中每個(gè)條件篩選后的輸出:
a.obj.constructor用于篩選出沒有constructor的對象一般由是自身沒有constructor哎壳,并且沒有屬性指向原型(由
Object.create(null)創(chuàng)建比如:noPrototype或者其他原型為空得構(gòu)造函數(shù)創(chuàng)建的比如:ownNoPrototype)
b.!core_hasOwn.call(obj, "constructor")用于篩選出有自身constructor屬性的對象(一般是對對象的構(gòu)造函數(shù)
自設(shè)置this.constructor = xxx;或者對象添加屬性constructor如obj.constructor = xxx;)所以這里可能會出
現(xiàn)bug,使得原型不是Object.prototype的構(gòu)造函數(shù)創(chuàng)建的對象在這里逃脫進(jìn)入下面繼續(xù)執(zhí)行,個(gè)人覺得這個(gè)條件去掉才
能夠篩選出需要的對象:沒有屬性指向原型的對象和有屬性指向Object.prototype原型的對象尚卫;因?yàn)樵诤竺娴拇a中沒有
對這里逃脫的對象進(jìn)行有效的處理(不知道jQuery設(shè)置這個(gè)條件的意義是什么);
c.!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf"),用于篩選出對象有屬性指向
Object.prototype原型的對象(一般是構(gòu)造函數(shù)原型指向Object.porototype的對象尸红,而原型不是
Object.prototyp的構(gòu)造函數(shù)通過為原型添加isPrototypeOf屬性的對象會逃脫吱涉,但是在后面代碼塊3會被過濾);
*/
if ( obj.constructor &&
!core_hasOwn.call(obj, "constructor") &&
!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897 為了兼容IE
return false;
}
###代碼片3:
/*
主要為了過濾原型不是Object.prototyp的構(gòu)造函數(shù)通過為原型添加isPrototypeOf屬性的對象比如:
owntransProtoProper對象,由于這種對象我們對他原型設(shè)置了對象外里,所以isPrototypeOf屬性是可以枚舉的怎爵,我
們只需要判斷該對象的原型中是否有可枚舉的屬性來達(dá)到目的,有因?yàn)槊杜e屬性總是從自身屬性枚舉到原型屬性盅蝗,所以
只需判斷對象最后一個(gè)可枚舉屬性不是他原型屬性鳖链;
*/
var key;
// 這里是快速獲取最后一個(gè)屬性
for ( key in obj ) {}
return key === undefined || core_hasOwn.call( obj, key );
},
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者