这是一个关于 JavaScript 如何添加对现有的引用而不是创建新的引用的问题。
在 Redux reducer 的上下文中,这里有一些示例希望足以说明问题,因为它是spread operator
or的熟悉位置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()