Javascript拡張オブジェクトextend実装
4311 ワード
jQueryの
最も一般的な使用シーンは、ダイアログボックスを表示するコンポーネントとして
このモードは多くの場所で使用されており、最も一般的な私たちは
まず,
非常に簡潔で分かりやすく、この実装方式はほとんどの場合のニーズを満たしていますが、この統合が浅いコピーであるという問題があります.マージされた属性にオブジェクト
上のコードは簡単な深いコピーを実現しました.しかし、ここにはもう一つの脆弱性があります.配列であれば、
テストコードは次のとおりです.
$.extend
メソッドは,いくつかのオブジェクトを統合し,深さコピーをサポートするために開発でよく用いられるメソッドである.最も一般的な使用シーンは、ダイアログボックスを表示するコンポーネントとして
option
オブジェクトパラメータを受信し、デフォルトパラメータdefaultOption
とマージして新しいパラメータを得るなど、パラメータのマージです.このような利点は、option
フィールドの拡張が非常に便利であり、使用者はパラメータの一部だけを送信することができ、その他はデフォルト値であり、コードの可読性も良好であることである.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
を使用してajaxリクエストを開始し、伝達されたoptionについてもこのように処理しています.現在のプロジェクトでは、Vueを使用しており、煩雑なDom操作を回避しているため、jQueryが提供するdom操作は使用できません.しかし、$.extend
の方法が必要です.彼のソースコードを調べた後、直接copyで使うつもりだったが、依存項目がたくさんあることに気づき、いちいち探すのがおっくうだったので、いっそ自分で最初から書いた.まず,
for in
を用いてソースオブジェクトを遍歴し,ターゲットオブジェクトの対応する属性を上書きする最も簡単なextend関数を実現すればよいと考えられる.var extend = function(destination,source) {
for(var property in source) {
destination[property] = source[property]
}
return destination
}
非常に簡潔で分かりやすく、この実装方式はほとんどの場合のニーズを満たしていますが、この統合が浅いコピーであるという問題があります.マージされた属性にオブジェクト
a
が含まれている場合、マージ後、destination
はオブジェクトaの参照を持ち、source
はオブジェクトa
の参照もあり、オブジェクトa
の属性を変更すると、destination
とsource
は同じオブジェクトを参照し、これが浅いコピーになります.深いコピー、すなわちdestination
のオブジェクトa
が参照ではなくコピーであることを実現するには、オブジェクトの付与値を追加的に判断し、処理する必要があります.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) { //
var copy = {}
destination[property] = extend(copy,obj,isDeep) // , obj , destination
} else {
destination[property] = obj
}
}
return destination
}
上のコードは簡単な深いコピーを実現しました.しかし、ここにはもう一つの脆弱性があります.配列であれば、
copy
を作成するときに新しい空の配列に設定する必要があります.そうすれば、for in
の操作拡張が正常に実行されます.さらにjQuery.extend
の実装形態を参照し、arguments
を用いて複数のオブジェクトのマージを処理する場合、最終的なコードは以下のように、extend
が比較的完全に実装され、参照に供される.バグがあればコメントを歓迎します.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
}
})()
テストコードは次のとおりです.
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