简体   繁体   English

替换对象值而不替换引用

[英]Replace object value without replacing reference

How can you update an entire object, say:如何更新整个对象,例如:

var x = {a:1}
function modify(obj) {
  obj = {b:2}
}
modify(x)
console.log(x) // {a:1}

But maintain the reference?但保持引用? I want the object to be modified outside the function.我希望在函数外修改对象。

My specific case is using lodash.pick inside my function:我的具体情况是在我的函数中使用lodash.pick

if (whitelist) {
  obj = _.pick(obj, whitelist)
}

I can't seem to find a pick function that modifies the object.我似乎找不到修改对象的pick函数。 Is there a way to do this or do I need to start returning copies of the object?有没有办法做到这一点,或者我是否需要开始返回对象的副本?

delete everything from the old object, and then add new properties, key-by-key: delete旧对象中的所有内容,然后逐个添加新属性:

 function modify(obj, newObj) { Object.keys(obj).forEach(function(key) { delete obj[key]; }); Object.keys(newObj).forEach(function(key) { obj[key] = newObj[key]; }); } var x = {a:1} modify(x, {b:42}) document.write(JSON.stringify(x));

If you're wondering whether it's a good idea in general, the answer is no.如果您想知道这是否是一个好主意,答案是否定的。 Construct a new object, return it from the function and assign - this is a much preferred way.构造一个新对象,从函数中返回它并赋值——这是一种更受欢迎的方式。

You can achieve this (not exactly what you want) if you wrap your object and change the modify function like this,如果您包装对象并像这样更改修改功能,您可以实现这一点(不完全是您想要的),

var wrapper = {};
wrapper.x = {a:1};
function modify(obj, key) {
    obj[key] = {b:2};
}
modify(wrapper, 'x');
console.log(wrapper.x); // {b:2}
/**
 * Method to deep update the values of the source object from new object without changing source  object reference
 *
 * @export
 * @param {*} sourceObj
 * @param {*} newObj
 */
export function updateObjKeepingRef(sourceObj: any, newObj: any): void {
  Object.keys(newObj).forEach(key => {
    // if value is object and instance is not Date
    if (newObj[key] && typeof newObj[key] === 'object' && sourceObj[key] && !(newObj[key] instanceof Date)) {
      updateObjKeepingRef(sourceObj[key], newObj[key]);
    } else {
      // updating properties
      sourceObj[key] = newObj[key];
    }
  });
}

I was having this issue.我遇到了这个问题。 After some research, I opted to convert objectTwo to a JSON string, and then replace objectOne with the parsed version.经过一番研究,我选择将 objectTwo 转换为 JSON 字符串,然后将 objectOne 替换为解析后的版本。 In other words:换句话说:

var mObjectOne = { ExampleProperty: 10 };
var mObjectTwo = { ExampleProperty: 15 };

// I wanted mObjectOne to hold the same data as mObjectTwo, but keep a separate reference
var mObjectTwoAsJSON = JSON.stringify(mObjectTwo);
mObjectOne = JSON.parse(mObjectTwoAsJSON);

// Now the references are still different, as desired, but the object data has been updated.

Thanks,谢谢,

obj = JSON.parse(JSON.stringify(newObj))

Why does modify not edit the object referred to by obj?为什么 modify 不编辑 obj 引用的对象?

Because inside modify when you write:因为在你写的时候里面修改

obj = {b:2}

Note that obj is a local variable to the function call of modify .请注意, objmodify函数调用的局部变量。 A new object {b:2} is created, and the local variable obj now refers to this new object.创建了一个新对象{b:2} ,并且局部变量obj现在引用了这个新对象。 Recall that the variable x still refers to the {a:1} object.回想一下变量 x 仍然引用{a:1}对象。

If x is a global variable AND if there is no local variable inside the function by the name, then you can do:如果x是一个全局变量,并且函数内部没有局部变量的名字,那么你可以这样做:

var x = {a:1};
function modify() {
  x = {b:2}
}
modify();
console.log(x) // {b:2}

Why does the above code work?为什么上面的代码有效?

When you call modify() , it tries to see if it has a local variable x, since it could not find one, it looks up in the scope chain.当您调用modify() 时,它会尝试查看它是否具有局部变量 x,因为找不到,它会在作用域链中查找。 The next scope to look for this function call is the global scope, and sure enough, there we have a x variable.寻找这个函数调用的下一个作用域是全局作用域,果然,我们有一个x变量。 Hence this global variable x 's value is set now.因此,现在设置了这个全局变量x的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM