Object.assign() - 奇怪的行为需要解释
Object.assign() - weird behaviour need explanation
我有这个代码:
function margeOptions(options, passedOptions) {
options = Object.assign(options, passedOptions);
}
let passedOpts = {a: true};
let opts = {a: false};
margeOptions(opts, passedOpts);
console.log(opts); // as expected returns {a: true}
但是当我稍微改变函数时,像这样:
function margeOptions(options, passedOptions) {
options = Object.assign({}, options, passedOptions);
}
let passedOpts = {a: true};
let opts = {a: false};
margeOptions(opts, passedOpts);
console.log(opts); // this time returns {a: false} <-- !
那么这里到底发生了什么?
Object.assign
设置对象的属性作为第一个参数;它也是 returns 同一个对象。因此,在您的第一个示例中,由于您将 option
作为第一个参数传递,因此它会使用 new/updated 属性进行更新。在您的第二个示例中,您没有将它作为第一个参数传递,它只是要从中读取属性的 "source" 对象之一,因此不会更新。
如果您对 赋值 没有更改 opts
的原因感到困惑,那是因为对参数赋值不会对函数外的任何内容产生任何影响。例如:
function foo(a) {
a = 42;
}
var x = 67;
foo(x);
console.log(x); // Still 67
那是因为 foo(x)
读取 x
的 值 并将其传递给 foo
。 a
和 x
之间没有任何联系,只是 a
的值最初来自 x
。
和opts
/options
完全一样。 mergeOptions(opts, passedOptions)
读取 opts
的 值 ,这是一个对象引用,并将该值传递给 mergeOptions
。该值与 opts
之间没有持续的联系。对象引用指向对象,而不是变量opts
.
Object.assign()
函数修改第一个对象参数的内容。因此在第一个函数中:
options = Object.assign(options, passedOptions);
您的代码有效,因为 options
是第一个参数。请注意,返回给 options
参数的赋值没有任何效果,或者至少没有任何有用的效果。它会将 Object.assign
的 return 值分配给 options
变量,但这是它已有的值。
第二个函数传递一个新构造的空对象作为第一个参数,这意味着作为options
传递的对象不会被修改。修改后的对象被分配回 options
,但因为它只是一个函数参数,不会更改调用环境中的引用。如果你想这样做,你必须 return 值并在调用环境中分配它。
我有这个代码:
function margeOptions(options, passedOptions) {
options = Object.assign(options, passedOptions);
}
let passedOpts = {a: true};
let opts = {a: false};
margeOptions(opts, passedOpts);
console.log(opts); // as expected returns {a: true}
但是当我稍微改变函数时,像这样:
function margeOptions(options, passedOptions) {
options = Object.assign({}, options, passedOptions);
}
let passedOpts = {a: true};
let opts = {a: false};
margeOptions(opts, passedOpts);
console.log(opts); // this time returns {a: false} <-- !
那么这里到底发生了什么?
Object.assign
设置对象的属性作为第一个参数;它也是 returns 同一个对象。因此,在您的第一个示例中,由于您将 option
作为第一个参数传递,因此它会使用 new/updated 属性进行更新。在您的第二个示例中,您没有将它作为第一个参数传递,它只是要从中读取属性的 "source" 对象之一,因此不会更新。
如果您对 赋值 没有更改 opts
的原因感到困惑,那是因为对参数赋值不会对函数外的任何内容产生任何影响。例如:
function foo(a) {
a = 42;
}
var x = 67;
foo(x);
console.log(x); // Still 67
那是因为 foo(x)
读取 x
的 值 并将其传递给 foo
。 a
和 x
之间没有任何联系,只是 a
的值最初来自 x
。
和opts
/options
完全一样。 mergeOptions(opts, passedOptions)
读取 opts
的 值 ,这是一个对象引用,并将该值传递给 mergeOptions
。该值与 opts
之间没有持续的联系。对象引用指向对象,而不是变量opts
.
Object.assign()
函数修改第一个对象参数的内容。因此在第一个函数中:
options = Object.assign(options, passedOptions);
您的代码有效,因为 options
是第一个参数。请注意,返回给 options
参数的赋值没有任何效果,或者至少没有任何有用的效果。它会将 Object.assign
的 return 值分配给 options
变量,但这是它已有的值。
第二个函数传递一个新构造的空对象作为第一个参数,这意味着作为options
传递的对象不会被修改。修改后的对象被分配回 options
,但因为它只是一个函数参数,不会更改调用环境中的引用。如果你想这样做,你必须 return 值并在调用环境中分配它。