Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 通过引用扩展对象_Javascript - Fatal编程技术网

Javascript 通过引用扩展对象

Javascript 通过引用扩展对象,javascript,Javascript,我有一个extend方法,它可以像您期望的那样在JavaScript中扩展对象: var objA = {a: true}; var objB = extend({b:false}, objA); console.log(objB); // {a: true, b: false} var objA = {a: false}; var objB = Object.create(objA); objB.b = false; console.log(objB.a, objB.b); // true

我有一个
extend
方法,它可以像您期望的那样在JavaScript中扩展对象:

var objA = {a: true};
var objB = extend({b:false}, objA);
console.log(objB); // {a: true, b: false}
var objA = {a: false};
var objB = Object.create(objA);
objB.b = false;

console.log(objB.a, objB.b); // true, 
objA.a = false;
console.log(objB.a, objB.b); // false, 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

我相当肯定,如果没有一个附加的helper方法,这是不可能的,该方法依赖于某种对象监视方法,每当对象发生变化时就会触发该方法

想法

我的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);
};
(l).extend=(l).merge=函数(){
变量args=(l).fn.\u args(参数[{
深:“布尔”
}, {
“*”:“对象:对象”
}
]),
目标=(l)。_对象| | args.obj,
键=[],
obj,objs,copy,key,i,o;
//收集要合并的潜在对象
objs=(l).filter(参数,函数(值,索引){
如果(索引!=“obj”&&
(l) .isPlainObject(value)和&!((l).isEqual(target,value))){
返回值;
}
});
//未全局选择目标对象时
如果(!args.obj){
target=objs.shift();
}
//未全局选择目标对象且仅选择单个对象时
//是否通过扩展库本身
如果(!(l)。_全局和对象长度){
目标=这个;
objs[0]=args.obj;
}
//当一个布尔值被传递时,进入深度
if(args.deep){
//用于防止永无止境循环的生成属性引用
(l) .每个(对象、函数(索引、值){
按键。按键((l)。按键(值));
键=(l)。展平(键);
});
//向所有嵌套对象添加特性
(l) .deep(目标、功能(深度、索引、目标、参考){
if((l).indexOf(键,索引)=-1){
对于(i=0;i
您在这里提到的正是JavaScript的原型继承:

var objA = {a: true};
var objB = extend({b:false}, objA);
console.log(objB); // {a: true, b: false}
var objA = {a: false};
var objB = Object.create(objA);
objB.b = false;

console.log(objB.a, objB.b); // true, 
objA.a = false;
console.log(objB.a, objB.b); // false, false
当然,如果
objB
覆盖
a
属性,您将丢失该链接,因为JavaScript将在对象
objB
中找到属性
a
,因此不会在原型链中查找

使用ECMAScript 5方法,您可以像这样扩展
函数:

function extend(properties, proto) {
  var object = Object.create(proto);
  var descriptor = {};

  Object.getOwnPropertyNames(properties).forEach(function(name) {
    descriptor[name] = Object.getOwnPropertyDescriptor(properties, name);
  });

  return Object.defineProperties(object, descriptor);
}


var objA = {a: true};
var objB = extend({b: false}, objA);
console.log(objB.a, objB.b); // true, false
objA.a = false;
console.log(objB.a, objB.b); // false, false

你能在你的扩展方法中发布代码吗?仅仅使用普通的原型继承怎么样<代码>objB.prototype=objA要产生这种级联效果,您必须使用Mattias提到的原型。这应该是可行的,但要注意它是一个真正的引用,即,如果您更改objA上的属性,您将在objB上看到更改,但反之亦然。