如何完全修改javascript引用对象

时间:2018-04-11 07:50:37

标签: javascript

我有以下问题:

库正在返回对象的引用。现在我不想只修改对象的单个部分,我想完全覆盖对象。

我的代码如下所示:

var options=getOptions();
options=newOptions;
// now do something with the new options.

但是当我运行此代码时,将删除引用并设置一个新引用。

那么如何将整个新对象复制到引用?

4 个答案:

答案 0 :(得分:0)

您正在用options替换您所指的对象,但这对任何对该库所具有的原始对象的引用都没有影响。你可以用getOptions的返回值做 nothing ,它将用一个全新的对象替换lib所拥有的对象;你所能做的就是改变它给你的对象的状态(添加,更改和/或删除属性)。

除非库为您提供了一种在内部更改其引用的对象的方法,否则您无法完全替换该对象(无需修改库)。

以下是一个例子来说明:

// Emulating the library:
var lib = (function() {
  var libOptions = {
    name: "original"
  };
  
  return {
    // The operation you said it has
    getOptions: function() {
      return libOptions;
    },
    // The operation it would need to have
    setOptions: function(newOptions) {
      libOptions = newOptions;
    }
  };
})();

var options = lib.getOptions();
options = {
  name: "replaced"
};

console.log(options.name);          // "replaced"
console.log(lib.getOptions().name); // "original"

lib.setOptions(options);

console.log(options.name);          // "replaced"
console.log(lib.getOptions().name); // "replaced"

当库为您提供对象的引用时,您在内存中会有类似的内容:

libOptions−−+
            |
            |   +−−−−−−−−−−−−−−−−−−+
            +−−>|     (object)     |
            |   +−−−−−−−−−−−−−−−−−−+
            |   | name: "original" |
options−−−−−+   +−−−−−−−−−−−−−−−−−−+

然后当您将options设置为其他内容时:

                +−−−−−−−−−−−−−−−−−−+
libOptions−−−−−>|     (object)     |
                +−−−−−−−−−−−−−−−−−−+
                | name: "original" |
                +−−−−−−−−−−−−−−−−−−+

                +−−−−−−−−−−−−−−−−−−+
options−−−−−−−−>|     (object)     |
                +−−−−−−−−−−−−−−−−−−+
                | name: "replaced" |
                +−−−−−−−−−−−−−−−−−−+

如您所见,设置optionslibOptions中的库引用没有任何影响。

这就是lib必须提供setOptions的原因。

当然,您可以再次更改对象的状态(前提是该库未提供防御性副本或冻结对象);

options.name = "updated";

这样做:

libOptions−−+
            |
            |   +−−−−−−−−−−−−−−−−−−+
            +−−>|     (object)     |
            |   +−−−−−−−−−−−−−−−−−−+
            |   | name: "updated"  |
options−−−−−+   +−−−−−−−−−−−−−−−−−−+

答案 1 :(得分:0)

我从您的问题中理解的是,您希望深度复制对象,以便原始对象完好无损,您可以修改其副本。如果错了,请纠正我。

var options=getOptions();

var copyOfObject = JSON.parse( JSON.stringify( options ));

答案 2 :(得分:0)

根据我的理解,你从一个库中获取一个对象,你想要更改一些键,同时保持对象的其余部分相同。

如果您想要更改的只有少数几个属性,则只需在您从库中接收的对象上分配值:

function getLibObject() {
  return {
    constantKey: 'constant',
    overridenKey: 'to be overriden',
  };
}
var libObject = getLibObject();
libObject.overridenKey = "has been overriden";
libObject.newKey = "A new key has been added";
console.log(JSON.stringify(combinedObject)); //{"constantKey":"constant","overridenKey":"has been overriden","newKey":"A new key has been added"}

如果要更改的对象中的键只有一个深度,则可以使用Object.assign创建一个新的“浅合并”对象。 (根据您要支持的浏览器,您可能需要填充)

function getLibObject() {
  return {
    constantKey: 'constant',
    overridenKey: 'to be overriden',
  };
}
var libObject = getLibObject();
var newOptions = {
  overridenKey: 'has been overriden',
  newKey: 'A new key has been added'
};
var combinedObject = Object.assign({}, libObject, newOptions);
console.log(JSON.stringify(combinedObject)); //{"constantKey":"constant","overridenKey":"has been overriden","newKey":"A new key has been added"}

如果您希望合并的深度超过一个级别,Object.assign将无效。您可以使用[Lodash merge]等实用程序功能或使用某些SO answers which solve this

function getLibObject() {
  return {
    constantKey: 'constant',
    nestedKey: {
      deepConstantKey: 'This is nested at the second level and should not change',
      deepOverrideKey: 'This is nested at the second level and should be overriden'
    }
  };
}
var libObject = getLibObject();
var newOptions = {
  nestedKey:{
     deepOverrideKey: 'This value has been overriden'
  }
};
var combined = _.merge({}, libObject, newOptions);
console.log(JSON.stringify(combined))
//{"constantKey":"constant","nestedKey":{"deepConstantKey":"This is nested at the second level and should not change","deepOverrideKey":"This value has been overriden"}}
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>

答案 3 :(得分:0)

感谢您的帮助。我理解这个问题。

我现在以非常脏的方式解决了这个问题...... 当我有修改选项时,我会销毁lib对象并创建一个新对象。这不是好方法,而是解决方案。