这是一个关于JavaScript如何添加对现有内容的引用而不是创建新内容的问题。
以下是一些有用的示例 - 在Redux reducer的上下文中,因为它是spread operator
或Object.assign()
的熟悉位置:
在这里看到我们只是返回一个带有字符串的对象文字,因此没有什么可以将参考文献拖到其他地方存在的东西。
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return {
props: 'something arbitray'
}
}
}
这是可疑问题:
我们正在返回一个对象字面值,但我们已经包含对
args[type]
的引用。首先,我需要肯定地知道,这是否会返回一个维护指向当前设置为args[type]
的链接的对象?如果args[type]
之后发生变异,是否会反映在此返回的对象中?
export default (state = {}, action) => {
switch (action.type) {
case SOME_ACTION:
return {
props: args[type]
}
}
}
以下是我怀疑不会出现此问题的两个例子:
我理解正确吗? JavaScript是否只复制属性而不保留对
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()
执行完全相同的操作并创建一个全新的对象,而不会因为保留对args[type]
的引用而存在非法可变性的风险?我需要能够在创建对象后依赖于对象的不可变状态。
我展示的第二个示例是否会保留对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)

更新问题
有没有办法复制non-primitive
(即:对象/数组)以便它打破此引用?
我注意到它不适用于Object.assign()
答案 0 :(得分:3)
var a = 5;
var b = a;
b是否维护对?的引用?不,不是的。 您正在传递值引用/值而不是父对象。
答案 1 :(得分:0)
答案似乎是,如果值是基元,它不是问题,因为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?
阅读浅层和深层复制也很有帮助,Hard Copy vs Shallow copy javascript
如果目标是一个对象,这就解决了这个问题:
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年,传播)