Javascript擴(kuò)展對(duì)象extend實(shí)現(xiàn)

jQuery的$.extend方法是我們?cè)陂_發(fā)中經(jīng)常用到的方法,用于合并若干個(gè)對(duì)象,且支持深度拷貝。

最常見的一個(gè)使用場(chǎng)景是參數(shù)的合并,比如我們要做一個(gè)顯示對(duì)話框的組件,接收一個(gè)option對(duì)象參數(shù),把它和默認(rèn)參數(shù)defaultOption合并,得到新的參數(shù)。這樣做的好處就是對(duì)option字段的拓展非常方便,并且使用者可以只傳部分參數(shù),其他均為默認(rèn)值,代碼可讀性也比較好。

var showDialog = (function() {
     var defaultOption = {
        title:'',
        width:500,
        close:function(){}
    }
    return function(option) {
        $.extend({},defaultOption,option);
    }
})()

showDialog({
    title:'',
    close:function() {
      console.log('dialog closed')
    }
})

這種模式在很多地方都用到,最常見的我們使用$.ajax發(fā)起ajax請(qǐng)求,對(duì)于傳遞的option也是這樣處理的。
在現(xiàn)在的項(xiàng)目中,由于用的是Vue,避免了繁瑣的Dom操作,所以用不到j(luò)Query提供的dom操作。但是我需要$.extend方法。在查看了他的源碼之后,本來打算直接copy過來使用,可是發(fā)現(xiàn)它有很多依賴項(xiàng),懶得一一去找,所以索性自己從頭寫一個(gè)。

我們可以考慮首先實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的extend函數(shù),即用for in遍歷源對(duì)象,覆蓋目標(biāo)對(duì)象的對(duì)應(yīng)屬性即可。

var extend = function(destination,source) {
    for(var property in source) {
        destination[property] = source[property]
    }
    return destination
}

非常簡(jiǎn)潔易懂,這種實(shí)現(xiàn)方式滿足了大部分情況下的需求,但存在一個(gè)問題,就是這種合并是淺拷貝。
如果合并的屬性中含有對(duì)象a,那么在進(jìn)行合并之后,destination擁有的是對(duì)象a的引用,而source對(duì)象也有對(duì)象a的引用,那么如果我們修改對(duì)象a的屬性,destinationsource都將被修改——它們引用的是同一個(gè)對(duì)象,這就是淺拷貝。我們想實(shí)現(xiàn)深拷貝,即在destination中的對(duì)象a是一份復(fù)制品,而不是引用,那么我們需要對(duì)對(duì)象的賦值做額外的判斷和處理。

var isObjFunc = function(name) {
    var toString = Object.prototype.toString
    return function() {
        return toString.call(arguments[0]) === '[object ' + name + ']'
    } 
}
var isObject = isObjFunc('Object'),
var extend = function(destination,source,isDeep) {
    var obj,copy
    for(var property in source) {
        obj = source[property]
        if(isDeep && isObject(obj) { // 判斷是深拷貝且這個(gè)屬性是純對(duì)象
            var copy = {}
            destination[property] = extend(copy,obj,isDeep) // 遞歸調(diào)用,創(chuàng)建一份obj的拷貝,賦值給destination
        } else {
            destination[property] = obj
        }
    }
    return destination
}

上面的代碼就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單深拷貝。但這里還有一個(gè)漏洞,如果是數(shù)組的話,創(chuàng)建copy的時(shí)候應(yīng)該設(shè)置為一個(gè)新的空數(shù)組,這樣for in操作擴(kuò)展才能正常執(zhí)行。再參考jQuery.extend的實(shí)現(xiàn)方式,利用arguments處理多個(gè)對(duì)象合并的情況,最終的代碼如下,較為完整的實(shí)現(xiàn)了extend,供參考。如果有bug歡迎留言指正。

var extend = (function() {
    var isObjFunc = function(name) {
        var toString = Object.prototype.toString
        return function() {
            return toString.call(arguments[0]) === '[object ' + name + ']'
        } 
    }
    var   isObject = isObjFunc('Object'),
        isArray = isObjFunc('Array'),
        isBoolean = isObjFunc('Boolean')
    return function extend() {
        var index = 0,isDeep = false,obj,copy,destination,source,i
        if(isBoolean(arguments[0])) {
            index = 1
            isDeep = arguments[0]
        }
        for(i = arguments.length - 1;i>index;i--) {
            destination = arguments[i - 1]
            source = arguments[i]
            if(isObject(source) || isArray(source)) {
                console.log(source)
                for(var property in source) {
                    obj = source[property]
                    if(isDeep && ( isObject(obj) || isArray(obj) ) ) {
                        copy = isObject(obj) ? {} : []
                        var extended = extend(isDeep,copy,obj)
                        destination[property] = extended 
                    }else {
                        destination[property] = source[property]
                    }
                }
            } else {
                destination = source
            }
        }
        return destination
    }
})()

測(cè)試代碼如下

var a = {name:1}
var b = {name:2}
var c = {name:3}
extend(true,a,b,{name:[a,b,c],value:a})
console.log(a)
console.log(a.name[0] === a) // false
console.log(a.value === a) // false
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進(jìn)階之旅閱讀 114,759評(píng)論 24 450
  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語(yǔ)言來說都是核心的概念。通過函數(shù)可以封裝任意多條語(yǔ)句,而且...
    道無虛閱讀 4,635評(píng)論 0 5
  • ALTRun Windows快速啟動(dòng)工具,靈活自主配置快捷鍵快速啟動(dòng)電腦上各類軟件的小工具。簡(jiǎn)單易用,智能匹配,你...
    cd2016閱讀 801評(píng)論 0 0
  • 靜態(tài)庫(kù) VS 動(dòng)態(tài)庫(kù) 靜態(tài)庫(kù):靜態(tài)庫(kù)在Objective-C里面以.a或者.framework作為后綴,目前開發(fā)者...
    王君爵閱讀 1,318評(píng)論 0 0
  • 女人的江山之十七 文|綠茉兒 看見蘭茉進(jìn)來了,他們都收起了笑聲。 蘭陵過來招呼說:“茉茉,你終于來了,我們正念叨你...
    陜北一姐閱讀 177評(píng)論 0 0