為什么我會想到寫這幾行代碼
在實(shí)際工作中膘魄,我們會使用許多或自主開發(fā)或第三方的工具乌逐,有些工具的配置文件相當(dāng)細(xì)節(jié),使用頻率低倒也罷了创葡,使用頻率高的話必然造成很多代碼冗余浙踢。所以我都會對這些工具做二次封裝,把不經(jīng)常改動的配置給予默認(rèn)值蹈丸。如果需要改動成黄,傳入新的配置覆蓋原來的配置即可。
起初我以為這是一項很簡單的需求
var json1 = { // 固定的配置
a: 1,
b: 2,
c: 3,
}
var json2 = { // 作為參數(shù)傳入的配置
a: 11,
d: 14,
}
json3 = { // 合并后的結(jié)果
a: 11,
b: 2,
c: 3,
d: 14,
}
如上述逻杖,確實(shí)很簡單∷嘉粒可事實(shí)是荸百,當(dāng)配置不再是僅僅一層嵌套時,常用的合并如$.extend
滨攻,for in
賦值就不再能再解決問題了
var json1 = {
a: 1够话,
b: {
b1: 'hello',
b2: 'world',
},
}
var json2 = {
b: { b2: 'china' },
c: 3,
}
json3 = { // 合并后的結(jié)果
a: 1,
b: { b2: 'chila' },
c: 3,
}
可以看出蓝翰,我們的本意是希望json2
里的b.b2: 'china'
取代json1
里的b.b2: 'world'
, 可是實(shí)際上,常規(guī)的結(jié)果只會把整個object/json
取代女嘲,而不會去遍歷其中的屬性畜份,在本例中導(dǎo)致了b.b1
的丟失。
于是就有了如下幾行代碼:
// 遇到相同元素級屬性欣尼,以后者(main)為準(zhǔn)
// 不返還新Object爆雹,而是main改變
function mergeJSON (minor, main) {
for (var key in minor) {
if (main[key] === undefined) { // 不沖突的,直接賦值
main[key] = minor[key];
continue;
}
// 沖突了愕鼓,如果是Object钙态,看看有么有不沖突的屬性
// 不是Object 則以main為主,忽略即可菇晃。故不需要else
if (isJSON(minor[key])) {
// arguments.callee 遞歸調(diào)用册倒,并且與函數(shù)名解耦
arguments.callee(minor[key], main[key]);
}
}
}
// 附上工具
function isJSON(target) {
return typeof target == "object" && target.constructor == Object;
}
雖然只有十幾行的代碼,但還是挺實(shí)用磺送。粗略的挖掘了一下搜索引擎驻子,好像并沒有更合適解決問題的代碼。簡單的遞歸思想和argument.callee
琢磨一下也是有些味道的