jQuery.extend()方法源碼解析

1.變量的含義:

var target
    ,options /* 指向源對(duì)象 */
    ,name,   /*  鍵名 */
    ,i = 1   /* 指向的源對(duì)象在arguments中的索引 */
    ,length = arguments.length /* 參數(shù)的個(gè)數(shù) */
    ,deep = false   /* 標(biāo)志是否深拷貝,沒有boolean值的時(shí)候默認(rèn)為flase谨履,淺復(fù)制 */
    ,src     /* 存儲(chǔ)target對(duì)象的當(dāng)前屬性 */
    ,copy    /* 存儲(chǔ)源對(duì)象當(dāng)前屬性的值 */
    ,target = arguments[0] || {} /* 過濾掉undefined 和 null */
    ,clone;  /* 深復(fù)制時(shí)候存放target[name]值 */
    ,copyIsArray; /* 存放一個(gè)標(biāo)志妓笙,表示源對(duì)象當(dāng)前屬性值是否是數(shù)組 */

2.if代碼塊1:extend函數(shù)提供用戶指定是否深拷貝的功能通過在第一個(gè)參數(shù)傳遞boolean值喳坠,檢測函數(shù)第一個(gè)值是否是boolean值停做。

2.1. 第一個(gè)參數(shù)是boolean時(shí)候執(zhí)行灸异。

2.2. 第一個(gè)參數(shù)是boolean類型即是target的指向錯(cuò)了,i指向也錯(cuò)了绍昂,必須進(jìn)行修改,并且重置deep標(biāo)志狂秦。
/* 1.第一個(gè)參數(shù)是boolean時(shí)候執(zhí)行灌侣,
   2.第一個(gè)參數(shù)是boolean類型即是target的指向錯(cuò)了,i指向也錯(cuò)了,必須進(jìn)行修改裂问,并且重置deep標(biāo)志
*/

if ( typeof target === "boolean" ) {
    deep = target;
    target = arguments[1] || {}; /* 過濾第2個(gè)參數(shù)值為undefined,null */
    i = 2;
}

3.if代碼塊2:因?yàn)閖s中對(duì)那些不是對(duì)象不是函數(shù)的值設(shè)置屬性方法是無效的,這里過濾這些值侧啼,保證target指向一個(gè)可以設(shè)置屬性的對(duì)象。

3.1. if語句:滿足target不是對(duì)象也不是函數(shù)時(shí)執(zhí)行堪簿。

3.2. 滿足條件的target值有可能是以字面量方式創(chuàng)建的boolean,number,string痊乾。

3.3. 不會(huì)出現(xiàn)target值為undefined和null,前面初始化時(shí)候已經(jīng)過濾椭更。
if ( typeof target !== "object" 
    && !jQuery.isFunction(target) ) {
    target = {};
}

4.if代碼塊3:extend()函數(shù)實(shí)現(xiàn)了當(dāng)傳入的參數(shù)有效對(duì)象個(gè)數(shù)不足夠賦值給target和源對(duì)象時(shí)哪审,默認(rèn)將target指向自身。

4.1. arguments長度等于i的值得時(shí)候虑瀑,表示target = arguments[arguments.length-1],
這時(shí)候的源對(duì)象是arguments[arguments.length] = undefined湿滓,顯然這是沒意義的滴须。

4.2. jQuery在出現(xiàn)這種情況時(shí),將target對(duì)象設(shè)置為自身叽奥,然后修改i指向target原先的指向扔水。

4.3. 我們可以通過這個(gè)方法對(duì)jQuery進(jìn)行擴(kuò)展。
if ( length === i ) {
target = this;
--i;
}

5.for代碼塊朝氓,實(shí)現(xiàn)target對(duì)象擴(kuò)展魔市,從第一個(gè)源對(duì)象開始遍歷arguments。

for ( ; i < length; i++ ) {

    /* 以上我們已經(jīng)將arguments中的項(xiàng)過濾到target指向赵哲,以下if在源對(duì)象值為undefiend和null時(shí)進(jìn)行過濾*/
    
    if ( (options = arguments[ i ]) != null ) {
        for ( name in options ) {
            src = target[ name ];
            copy = options[ name ];
            
            /* 為了避免在遞歸深拷貝過程中待德,出現(xiàn)了無限循環(huán):(看后面代碼片1,2)
               1.向extend()方法傳入的源對(duì)象擁有屬性值為目標(biāo)對(duì)象枫夺,并且目標(biāo)對(duì)象中有屬性引用了目標(biāo)對(duì)象本身将宪,
               2.源對(duì)象的屬性引用了源對(duì)象自身*/
               
            if ( target === copy ) {
                continue;
            }
        
            /* 判斷是否滿足深拷貝的條件:
            1.deep標(biāo)志為true,
            2.源對(duì)象當(dāng)前屬性(name)的值存在,
            3.源對(duì)象當(dāng)前屬性值是數(shù)組,{}或者是由Object創(chuàng)建的對(duì)象*/
            
            if ( deep 
                 && copy 
                 && ( jQuery.isPlainObject(copy) 
                 || (copyIsArray = jQuery.isArray(copy)) ) ) {
            
                /* copyIsArray 是標(biāo)示源對(duì)象當(dāng)前屬性值是否是數(shù)組,通過這個(gè)標(biāo)志分別對(duì)源對(duì)象當(dāng)前屬性
                值為對(duì)象和源對(duì)象當(dāng)前屬性值為數(shù)組的情況分開處理*/
                
                if ( copyIsArray ) {
                
                    /* 如果不設(shè)置為false,下一次既使?jié)M足深拷貝的條件進(jìn)入后橡庞,如果源對(duì)象當(dāng)前屬性值為對(duì)象涧偷,會(huì)按照數(shù)組進(jìn)行處理*/
                    copyIsArray = false;
                    
                    /* clone存放了target[name]的值,值的如果不存在或者類型不是數(shù)組時(shí)毙死,將其賦值空數(shù)組燎潮,否則值不改變 */
                    clone = src && jQuery.isArray(src) ? src : [];
                    
                    } else {
                    clone = src && jQuery.isPlainObject(src) ? src : {};
                    }
                    
                    /* 遞歸調(diào)用extend進(jìn)行深拷貝*/
                    target[ name ] = jQuery.extend( deep, clone, copy );
                    
                    /* 過濾源對(duì)象屬性值為undefined的屬性,沒有過濾屬性值為null的屬性,看以下代碼片3*/
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }
    
    /* 返回修改后的對(duì)象*/
    return target;
};

6.代碼片1

/* 1.target對(duì)象屬性值引用自身扼倘,并且original對(duì)象的屬性引用target,注釋if(target == copy)中的continue后無限循環(huán)最后
報(bào)錯(cuò)*/
/* 2.錯(cuò)誤信息:Uncaught RangeError: Maximum call stack size exceeded(超過最大調(diào)用堆棧內(nèi)存)*/
var target = {};
target.proper = target;
var original = {};
original.proper = target;
$.extend(true,target,original);
注釋continue

運(yùn)行結(jié)果

7.代碼片2

 /*bug:
 2.original對(duì)象存在屬性引用其自身,報(bào)錯(cuò)信息和上面一致 */
var target = {};
target.proper = '屬性';
var original = {};
original.proper = original;
console.log($.extend(true,target,original));

8.代碼片3

/* 過濾掉屬性值為undefiend的屬性确封,沒過濾屬性值為null的屬性,可以測試以下代碼:可以修改copy!= undefined來實(shí)現(xiàn)過濾null*/
var target = {}
var original = {
   name: null
}
console.log($.extend(target,original));
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末再菊,一起剝皮案震驚了整個(gè)濱河市爪喘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纠拔,老刑警劉巖秉剑,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異稠诲,居然都是意外死亡侦鹏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門臀叙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來略水,“玉大人,你說我怎么就攤上這事劝萤≡ɡ裕” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跨释。 經(jīng)常有香客問我胸私,道長,這世上最難降的妖魔是什么鳖谈? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任盖文,我火速辦了婚禮,結(jié)果婚禮上蚯姆,老公的妹妹穿的比我還像新娘。我一直安慰自己洒敏,他們只是感情好龄恋,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凶伙,像睡著了一般郭毕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上函荣,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天显押,我揣著相機(jī)與錄音,去河邊找鬼傻挂。 笑死乘碑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的金拒。 我是一名探鬼主播兽肤,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼绪抛!你這毒婦竟也來了资铡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤幢码,失蹤者是張志新(化名)和其女友劉穎笤休,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體症副,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡店雅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贞铣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片底洗。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咕娄,靈堂內(nèi)的尸體忽然破棺而出亥揖,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布费变,位于F島的核電站摧扇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏挚歧。R本人自食惡果不足惜扛稽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滑负。 院中可真熱鬧在张,春花似錦、人聲如沸矮慕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痴鳄。三九已至瘟斜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痪寻,已是汗流浹背螺句。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留橡类,地道東北人蛇尚。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像顾画,于是被迫代替她去往敵國和親佣蓉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法亲雪,類相關(guān)的語法勇凭,內(nèi)部類的語法,繼承相關(guān)的語法义辕,異常的語法虾标,線程的語...
    子非魚_t_閱讀 31,587評(píng)論 18 399
  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,212評(píng)論 0 4
  • 1.JQuery 基礎(chǔ) 改變web開發(fā)人員創(chuàng)造搞交互性界面的方式。設(shè)計(jì)者無需花費(fèi)時(shí)間糾纏JS復(fù)雜的高級(jí)特性灌砖。 1....
    LaBaby_閱讀 1,325評(píng)論 0 2
  • Elasticsearch 需要依賴 Java 8+ 環(huán)境璧函。 跟著 官方文檔 安裝 Elasticsearch。直...
    與蟒唯舞閱讀 300評(píng)論 0 1
  • Author: Zongwei Zhou | 周縱葦Weibo: @MrGiovanniEmail: zongwe...
    MrGiovanni閱讀 4,957評(píng)論 0 12