添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
当我们尝试更改已冻结对象的属性或使用 Object.defineProperties() 定义属性时,会发生错误“Cannot assign to read only property of Object”。

要解决该错误,需要创建对象或数组的副本,或将属性设置为可写。

以下是发生上述错误的 3 个示例。

// 👇️ 使用 OBJECTS 👇️ const obj = { name : 'James' , Object . freeze (obj); // ⛔️ Error: Cannot assign to read only property 'name' of object '#<Object>' obj. name = 'Fql' ; // ------------------------------------------------------ // 👇️ 使用 ARRAYS 👇️ const arr = [ 'a' , 'b' , 'c' ]; Object . freeze (arr); // ⛔️ Error: Cannot assign to read only property '0' of object '[object Array]' arr[ 0 ] = 'z' ; // ------------------------------------------------------ // 👇️ 使用 Object.defineProperties() 👇️ const obj2 = {}; Object . defineProperties (obj2, { country : { value : 'Germany' , // 👉️ 必须设置为 writable: true // writable: true, // 👈️ 这里取消注释 // ⛔️ Error: Cannot assign to read only property 'country' of object '#<Object>' obj2. country = 'Austria' ; 前两个错误的发生是因为对象或数组已被 Object.freeze() 方法冻结。

错误的常见原因 “Cannot assign to read only property of object”错误的最常见原因是:

试图将属性分配给冻结的对象或数组。 使用 Object.defineProperties 时忘记将 writable 设置为 true 。 在使用第三方库(例如 React.js)时尝试就地修改状态对象或数组。 创建数组或对象的副本 无法再更改冻结的对象,但我们可以创建数组或对象的副本并更改副本。

// ✅ 使用 OBJECTS const obj = { name : 'James' , Object . freeze (obj); const objCopy = {...obj}; // 👈️ 创建副本 objCopy. name = 'Fql' ; console . log (objCopy); // 👉️ {name: 'Fql'} // -------------------------------------- // ✅ 使用 ARRAYS const arr = [ 'a' , 'b' , 'c' ]; Object . freeze (arr); const arrCopy = [...arr]; // 👈️ 创建副本 arrCopy[ 0 ] = 'z' ; console . log (arrCopy); // 👉️ ['z', 'b', 'c'] 我们使用扩展语法 ... 创建对象和数组的副本,因此我们可以更改它们。

尝试对只读数组进行排序 当我们尝试对只读数组进行排序时也会发生此错误,因为 Array.sort() 方法会在适当的位置对数组进行排序。

const arr = [ 'a' , 'b' , 'c' ]; Object . freeze (arr); // ⛔️ TypeError: Cannot assign to read only property '0' of object '[object Array]' arr. sort (); 要解决该错误,请创建数组的副本并对副本进行排序。

const arr = [ 'a' , 'b' , 'c' ]; Object . freeze (arr); // 👇️ 创建副本 const arrCopy = [...arr]; // 👇️ 对副本排序 arrCopy. sort (); console . log (arrCopy); // 👉️ [ 'a', 'b', 'c' ] 我们使用扩展语法 ... 创建数组的副本,并在副本上调用 sort() 方法。

现在我们不再试图改变只读数组。

我们还可以使用 Array.slice() 方法创建冻结数组的浅表副本。

const arr = [ 'a' , 'b' , 'c' ]; Object . freeze (arr); // 👇️ 创建数组的浅表副本 const arrCopy = arr. slice (); arrCopy. sort (); console . log (arrCopy); // 👉️ [ 'a', 'b', 'c' ] 当不带任何参数调用 slice() 方法时,它返回原始数组的浅表副本。

如果使用 Object.defineProperties() ,将 writable 设置为 true 如果在使用 Object.defineProperties 方法时出现错误,如果要更改其值,请将属性设置为可写。

const obj2 = {}; Object . defineProperties (obj2, { country : { value : 'Germany' , writable : true , // 👈️ 将属性设置为可写 obj2. country = 'Austria' ; console . log (obj2. country ); // 👉️ "Austria" country 属性设置为可写,因此可以更改。

使用 Object.defineProperties() 方法时,可写参数默认为 false。

如果我们希望能够更改属性的值,请将 writable 显式设置为 true

我们可能必须在对象上设置的其他属性是可配置和可枚举的:

configurable - 如果为 false,则无法删除或更改该属性。 默认为假。 enumerable - 如果为 true,则该属性在循环中迭代。 默认为假。 writable - 如果为 false,则不能更改属性的值 const obj2 = {}; Object . defineProperties (obj2, { country : { value : 'Germany' , writable : true , // 👈️ 将属性设置为可写 configurable : true , enumerable : true , console . log (obj2); obj2. country = 'Austria' ; console . log (obj2. country ); // 👉️ "Austria" 我们还将可枚举和可配置属性设置为 true

configurable 设置为 true 时,可以删除该属性。 该属性的默认值为 false

enumerable 设置为 true 时,该属性将在循环中迭代。 该属性的默认值为 false

将对象传递给 Object.freeze 方法 如果将对象或数组传递给 Object.freeze ,则不能:

向其添加新属性或元素 删除现有属性 更改现有属性 解决此问题的最佳方法是创建对象或数组的副本并更改副本。

使用带有冻结状态对象和数组的第三方库 如果我们使用某些已冻结状态对象或数组的第三方库,我们很可能不应该直接改变 state 对象。

该库可能会导出一个应该用于更改 state 的方法。

使用 React.js 等库时,不应直接修改状态。

相反,该库提供了可用于更改状态的方法和钩子。

如果我们从库中获取的对象被标记为只读,那么这是有意为之,因为用户不应直接修改它们。

要解决“Cannot assign to read only property of Object”错误:

确保在设置属性之前创建冻结对象或数组的副本。 如果我们使用 Object.defineProperties ,请将可写属性设置为 true。 确保不要修改 React.js 等库中的状态对象,并使用内置方法设置状态。
  • JavaScript 中 Unexpected end of JSON input 错误
  • 你理解Javascript的闭包吗?
  • 如何在 JavaScript 中将集合set转换为 JSON
  • 如何在 JavaScript 中存储键值数组
  • 你需要知道的关于Javascript 中的 Let 关键词的一切
  • 在 JavaScript 中获取字符串的最后 N 个字符
  • JavaScript 中如何检查函数是否定义
  • 在 JavaScript 中从数组中删除重复的内容
  • 在 JavaScript 中将数字四舍五入到小数点后两位
  •