Javascript 在执行switch语句的数组中迭代返回TypeError:cannotassign to read only property';地点';对象的'#&书信电报;对象>';

Javascript 在执行switch语句的数组中迭代返回TypeError:cannotassign to read only property';地点';对象的'#&书信电报;对象>';,javascript,arrays,switch-statement,Javascript,Arrays,Switch Statement,我有一个只读数组,我将它复制成一个可变数组let mutableForecast=[…forecast]我将获取这个新数组,并使用forEach对其进行迭代,这样我就可以对数组进行变异。我试图用一个开关语句使用一些流控制,但我得到类型错误:无法分配给对象“#”的只读属性“location” 这里有什么问题?我看过,还有其他一些,但找不到答案 这就是我复制预测数组之前的样子 如果不知道forecast从何而来,很难确定,但我怀疑问题在于数组的元素不是普通对象,而是定义为不可变的自定义类型的实例。您

我有一个只读数组,我将它复制成一个可变数组
let mutableForecast=[…forecast]
我将获取这个新数组,并使用
forEach
对其进行迭代,这样我就可以对数组进行变异。我试图用一个
开关
语句使用一些流控制,但我得到
类型错误:无法分配给对象“#”的只读属性“location”

这里有什么问题?我看过,还有其他一些,但找不到答案

这就是我复制预测数组之前的样子
如果不知道
forecast
从何而来,很难确定,但我怀疑问题在于数组的元素不是普通对象,而是定义为不可变的自定义类型的实例。您的第三个链接具有可能的解决方案。关键是,不能简单地通过这种方式使用rest&spread将不可变的数组转换为可变的数组。您需要分别修改数组中每个项的可变性

你可能需要这样的东西:

let mutableForecast=[…forecast]
可变预测。forEach((obj,i)=>{
//使此元素的位置属性可变
Object.defineProperty(obj,'location',{writable:true})
//计算并设置新值
开关(目标位置){
“不列颠哥伦比亚”案:
obj.location='BC'
打破
违约:
对象位置='其他'
}
})

这可能也有用,而且我认为它更干净。您必须尝试一下,以确保:

let mutableForecast=Array.from(预测)
.map(预测项=>({
…预测,
位置:getShortLocation(预测项位置)
}))
函数getShortLocation(sourceLocation){
开关(源位置){
案例“不列颠哥伦比亚”:返回“不列颠哥伦比亚”
默认值:返回“其他”
}
}

我们正在解决的核心问题是,无论包提供什么
forecast
,它都会在某些自定义数据类型中进行传输,其中一些属性被定义为不可变的。当您记录对象时,这一事实不会出现,当您将类似于数组的容器转换为数组时,这一事实也不会改变

这是因为
[…forecast]
不编辑项目,它只是将它们从一个数据结构复制到另一个数据结构中。实际上,精确地说,它将对这些对象的引用复制到一个新数组中。如果原始对象是具有锁定属性的奇怪对象,那么新数组将由具有锁定属性的奇怪对象组成。如果要更改每个元素上该属性的值,则需要在更改之前重新定义该属性

考虑这样一个案例:

让我的狗={
品种:'狗',
姓名:“菲多”
}
//>myDog{品种:'dog',名称:'Fido'}
我们可以创建另一个具有相同属性的对象,如下所示:

让全等动物={
…我的狗
}
//>全等动物{物种:'dog',名称:'Fido'}
如果相同的属性名称出现两次,引擎将只接受最后一个:

让我的狗={
种类:'猫',
名称:'Fido',
物种:'狗'//这将导致猫被忽略
}
//>myDog{name:'Fido',species:'dog'}
因此,我们可以在复制时重写单个对象属性,方法是最后重新声明这些属性:

让另一个一致的动物={
…我的狗,
品种:“新狗”
}
//>另一种动物{名称:'Fido',物种:'newdog'}
这就是第二段的内容。这是一个扩展版本:

//创建一个元素为*引用*的实数组
//数组中的对象类似于预测
让ArrayOfImmutableForecast=Array.from(预测)
//创建另一个真实的新对象数组
//其属性名称、值和元数据是
//与源对象相同
让arrayOfMutableForecasts=arrayOfImmutableForecasts.map(originalObject=>{
让newObject={
//我认为这也将保留像不变性这样的特殊规则
…原始对象,
//在完成对象之前,我们声明一个新的简单属性
//引擎将从上面删除隐含的属性声明
//并根据这个简单的声明定义道具
位置:“新值”
}
返回新对象
})

似乎不允许更改数组中对象的位置属性。。。 您可以尝试创建对象的克隆并对其进行变异:

let mutableForecast=[…forecast]
mutableForecast=mutableForecast.map(obj=>{
常量位置=对象位置
常量objClone={}
用于(obj中的常量键){
如果(键!=='location')对象克隆[key]=obj[key]
}
开关(位置){
“不列颠哥伦比亚”案:
objClone.location=“BC”
打破
违约:
objClone.location=“其他”
}
返回对象克隆
})
如果失败,您可以尝试创建一个新属性,然后读取该属性:

let mutableForecast=[…forecast]
可变预测。forEach((obj,i)=>{
开关(目标位置){
“不列颠哥伦比亚”案:
obj.newLocation=“BC”
打破
违约:
obj.newLocation=“其他”
}
})

告诉我们
forecast
的来源可能会有所帮助。这是什么?我更新了问题以显示初始对象的外观,但第二个示例有效。你能解决的问题是什么。我真的不明白你的数组副本和我的有什么不同。
let mutableForecast = [...forecast]
mutableForecast.forEach((obj, i) => {
    switch (obj.location) {
        case obj.location === "BRITISH_COLUMBIA":
            obj.location = "BC"
            break;
        default:
            obj.location = "oother"
    }

})