Javascript属性作为对其他对象属性的引用

时间:2014-12-17 22:41:46

标签: javascript object reference

有没有办法将一个对象的属性指定为另一个对象的属性的引用,并动态地这样做?请注意,在for循环中,我跳过了与第二个对象同名的任何属性。我正在研究一个框架,它将JSON缓存为具有行为的对象,并允许ORM类型的行为,我可以将缓存的对象和集合作为其他缓存对象的属性。我需要跳过某些属性以避免循环引用。

var obj1 = {
    prop1: "hey",
    obj2:"you",
    prop2: "come over here"
}

var obj2 = {}

for(var prop in obj1){
    if(prop != 'obj2'){
        obj2[prop] = obj1[prop];
    }
}
console.log(obj1);
console.log(obj2);

obj1.prop2 = "come on, man";

console.log(obj1);
console.log(obj2);
//obj1 is unchanged in output.  I would like to be able to update it by mutating obj2's properties

小提琴:http://jsfiddle.net/6ncasLb0/1/

如果无法做到这一点,是否可以在不改变原始对象的情况下删除或改变引用的属性?我知道,可能不是。只是在黑暗中拍摄。

1 个答案:

答案 0 :(得分:2)

我猜你最接近它的方法是确保你要改变它的属性与你在两个对象上获得的属性相同,所以你需要做一些工作以确保它们能够知道"知道& #34;当它们被实例化时彼此相对(例如,从原始对象克隆)

作为一个例子,您可以使用这样的简化模型,在其创建中标记的任何属性也将更新原始对象,尽管在对象上定义的新属性应该没问题。请注意,枚举和仅引用属性不起作用,至少不使用字符串(从1个对象复制到另一个对象时对象会发生变化)



;
(function(namespace) {
  function addProperty(obj, property, valueholder) {
    Object.defineProperty(obj, property, {
      get: function() {
        return valueholder[property];
      },
      set: function(val) {
        valueholder[property] = val;
      },
      enumerable: true,
      configurable: false
    });
  }

  var model = namespace.model || function(options) {
    if (typeof options === 'undefined') {
      options = {};
    }
    var propHolder = options.container || {},
      prop;
    if (typeof options.props != null) {
      for (prop in options.props) {
        if (options.props.hasOwnProperty(prop)) {
          addProperty(this, prop, propHolder);
          propHolder[prop] = options.props[prop];
        }
      }
    };

    namespace.model.prototype.clone = function() {
      var options = {
          props: {},
          container: propHolder
        },
        prop;
      for (prop in this) {
        if (this.hasOwnProperty(prop)) {
          options.props[prop] = this[prop];
        }
      }
      return new namespace.model(options);
    };

    namespace.model.prototype.toString = function() {
      var prop, msg, props = [];
      for (prop in propHolder) {
        if (propHolder.hasOwnProperty(prop)) {
          props.push(prop + ': "' + this[prop].toString() + '"');
        }
      }
      return '[Model] {' + props.join(', ') + '}';
    }

    return this;
  };

  namespace.model = model;
}(window));

var obj1 = new model({
  props: {
    prop2: "come over here"
  }
});
obj1.prop1 = 'Hey';
obj1.obj2 = 'You';
obj1.test = {
  a: 10
};

var obj2 = obj1.clone();

console.log('-- before changes --');
console.log(obj1.toString());
console.log(obj2.toString());

obj2.prop2 = "come on, man";
obj2.prop1 = "won't change";
obj2.obj2 = "also not";
obj2.test.b = "both have this now";

console.log('-- after changes --');
console.log(obj1.toString());
console.log(obj2.toString());

console.log(obj1.test);
console.log(obj2.test);