我有一个extend
方法可以扩展对象,就像您在 JavaScript 中所期望的那样:
var objA = {a: true};
var objB = extend({b:false}, objA);
console.log(objB); // {a: true, b: false}
但是,我想通过引用将源的 ( objA
) 属性扩展到目标 ( objB
) 对象,以便对源所做的任何更改在事后反映在目标中,如下所示:
var objA = {a: true};
var objB = extend({b: false}, objA);
console.log(objB); // {a: true, b:false}
objA.a = false;
console.log(objB); // {a: false, b:false}
例如,当您修改一个对象(始终通过引用分配)时,事情正在按照我希望的方式工作:
var objA = {A:{a: true}};
var objB = _.extend({b: false}, objA);
console.log(objB) // {A:{a:true}, b:false};
objA.A.a = false;
console.log(objB); // {A:{a:false}, b:false};
因此,换句话说,当对objA
的非对象文字属性(或任何未通过引用分配的值)进行更改时,我希望这些更改反映在objB
.
我相当确定如果没有额外的辅助方法,这完全不可能,该方法依赖于某种对象监视方法,该方法在对象更改时触发。
想法?
我的extend
方法中的代码:
(l).extend = (l).merge = function () {
var args = (l).fn.__args(arguments, [{
deep: 'bool'
}, {
'*': 'obj:object'
}
]),
target = (l)._object || args.obj,
keys = [],
obj, objs, copy, key, i, o;
// Collect potential objects to merge
objs = (l).filter(args, function (value, index) {
if (index !== "obj" &&
(l).isPlainObject(value) && !((l).isEqual(target, value))) {
return value;
}
});
// When target object is not selected globally
if (!args.obj) {
target = objs.shift();
}
// When target object is not selected globally and only a single object
// is passed extend the library itself
if (!(l)._global && !objs.length) {
target = this;
objs[0] = args.obj;
}
// When a boolean is passed go deep
if (args.deep) {
// Build property reference used to prevent never ending loops
(l).each(objs, function (index, value) {
keys.push((l).keys(value));
keys = (l).flatten(keys);
});
// Add properties to all nested objects
(l).deep(target, function (depth, index, obj, ref) {
if ((l).indexOf(keys, index) === -1) {
for (i = 0; i < objs.length; i++) {
for (key in objs[i]) {
if ((l).isPlainObject(obj)) {
copy = objs[i][key];
obj[key] = copy;
}
}
}
}
}, "*");
}
// Merge first level properties after going deep
for (i = 0; i < objs.length; i++) {
if ((obj = objs[i]) !== null) {
for (key in obj) {
copy = obj[key];
if (target === copy) {
continue;
}
target[key] = copy;
}
}
}
return (l).fn.__chain(target);
};