当使用对象文字语法创建对象时,JavaScript 是否维护对现有变量的引用?
Does JavaScript maintain a reference to existing variables when objects are created using object literal syntax?
这是一个关于 JavaScript 如何添加对现有而不是创建新引用的问题。
这里有一些示例,希望足够说明,在 Redux reducer 的上下文中,因为它是 spread operator
或 Object.assign()
:
熟悉的地方
See here we are just returning an object literal with a string, so there is nothing that could drag in a reference to something that is existing elsewhere.
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return {
props: 'something arbitray'
}
}
}
这个是可疑问题:
We are returning an object literal but we have included reference to args[type]
. First, I need to know for certain, is this returning an object that maintains a link to whatever args[type]
is currently set to? If args[type]
were to get mutated after, would that be reflected in this returned object?
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return {
props: args[type]
}
}
}
这里有两个我怀疑不会有这个问题的例子:
Do I understand that correctly? Does JavaScript copy just the property and not maintain any reference to args[type]
?
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return Object.assign({}, state, { props: args[type] })
}
}
这是我最近了解到的另一个示例,可能在语法上与 Object.assign()
语法相同:
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return { ...state, props: args[type] }
}
}
问题:
扩展运算符在这种情况下是否做与 Object.assign()
完全相同的事情并创建一个全新的对象而没有由于维护对 [=20= 的引用而导致非法可变性的风险]?我需要能够依赖对象创建后的不可变状态。
我展示的第二个例子会保持对 args[type]
的实时引用吗?
我有一些代码通常会在某些东西中传播,我有一个忽略传播的用例,所以我很好奇这是否会成为问题。我如何保证 args[type]
的随机更改不会影响这个返回的对象?
这是正确答案吗?:
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return Object.assign({}, { props: args[type] })
}
}
[编辑]
我可以通过这样做来重现该问题:
const arr = ['one', 'two', 'three']
const args = {
type: arr
}
const something = {
props: args.type
}
arr.push('four') // Notice how this appears in something.props
console.log(something)
这修复了它(所以它似乎与基元和维护对象引用有关):
const arr = ['one', 'two', 'three']
const args = {
type: arr[2]
}
const something = {
props: args.type
}
arr[2] = 'what' // Notice how this doesn't appear in something.props
console.log(something)
Updated Question
有没有办法复制 non-primitive
(即:object/array)以破坏此引用?
我注意到它不适用于 Object.assign()
var a = 5;
var b = a;
b 是否维护对 a 的引用?不,不是的。
您正在传递一个值 reference/value 而不是父对象。
答案似乎是,如果值是原始值,这不是问题,因为 JavaScript 不存储对原始值的引用。
这里的解决方案是在对象或数组中散布为 属性:
const arr = ['one', 'two', 'three']
const args = {
type: arr
}
const something = {
props: [...args.type]
}
arr.push('four') // notice how this isn't included
console.log(something)
这很有帮助:Is JavaScript a pass-by-reference or pass-by-value language?
阅读浅拷贝和深拷贝也很有帮助,
这解决了目标是对象时的问题:
const obj = {
one: 'uno',
two: 'dos',
three: 'tres'
}
const args = {
type: obj
}
const something = {
props: Object.assign({}, args.type)
}
obj.four = 'four' // notice how this isn't included
console.log(something)
我记得 Eric Elliot 在一本书中也描述了这一点。 Object.assign()
是放弃该引用的关键。 (现在是 2017 年,传播)
这是一个关于 JavaScript 如何添加对现有而不是创建新引用的问题。
这里有一些示例,希望足够说明,在 Redux reducer 的上下文中,因为它是 spread operator
或 Object.assign()
:
See here we are just returning an object literal with a string, so there is nothing that could drag in a reference to something that is existing elsewhere.
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return {
props: 'something arbitray'
}
}
}
这个是可疑问题:
We are returning an object literal but we have included reference to
args[type]
. First, I need to know for certain, is this returning an object that maintains a link to whateverargs[type]
is currently set to? Ifargs[type]
were to get mutated after, would that be reflected in this returned object?
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return {
props: args[type]
}
}
}
这里有两个我怀疑不会有这个问题的例子:
Do I understand that correctly? Does JavaScript copy just the property and not maintain any reference to
args[type]
?
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return Object.assign({}, state, { props: args[type] })
}
}
这是我最近了解到的另一个示例,可能在语法上与 Object.assign()
语法相同:
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return { ...state, props: args[type] }
}
}
问题:
扩展运算符在这种情况下是否做与
Object.assign()
完全相同的事情并创建一个全新的对象而没有由于维护对 [=20= 的引用而导致非法可变性的风险]?我需要能够依赖对象创建后的不可变状态。我展示的第二个例子会保持对
args[type]
的实时引用吗?
我有一些代码通常会在某些东西中传播,我有一个忽略传播的用例,所以我很好奇这是否会成为问题。我如何保证 args[type]
的随机更改不会影响这个返回的对象?
这是正确答案吗?:
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return Object.assign({}, { props: args[type] })
}
}
[编辑] 我可以通过这样做来重现该问题:
const arr = ['one', 'two', 'three']
const args = {
type: arr
}
const something = {
props: args.type
}
arr.push('four') // Notice how this appears in something.props
console.log(something)
这修复了它(所以它似乎与基元和维护对象引用有关):
const arr = ['one', 'two', 'three']
const args = {
type: arr[2]
}
const something = {
props: args.type
}
arr[2] = 'what' // Notice how this doesn't appear in something.props
console.log(something)
Updated Question
有没有办法复制 non-primitive
(即:object/array)以破坏此引用?
我注意到它不适用于 Object.assign()
var a = 5;
var b = a;
b 是否维护对 a 的引用?不,不是的。 您正在传递一个值 reference/value 而不是父对象。
答案似乎是,如果值是原始值,这不是问题,因为 JavaScript 不存储对原始值的引用。
这里的解决方案是在对象或数组中散布为 属性:
const arr = ['one', 'two', 'three']
const args = {
type: arr
}
const something = {
props: [...args.type]
}
arr.push('four') // notice how this isn't included
console.log(something)
这很有帮助:Is JavaScript a pass-by-reference or pass-by-value language?
阅读浅拷贝和深拷贝也很有帮助,
这解决了目标是对象时的问题:
const obj = {
one: 'uno',
two: 'dos',
three: 'tres'
}
const args = {
type: obj
}
const something = {
props: Object.assign({}, args.type)
}
obj.four = 'four' // notice how this isn't included
console.log(something)
我记得 Eric Elliot 在一本书中也描述了这一点。 Object.assign()
是放弃该引用的关键。 (现在是 2017 年,传播)