迹忆客 专注技术分享

当前位置:主页 > 学无止境 > WEB前端 > JavaScript >

JavaScript 中 Cannot assign to read only property of Object 错误

作者:迹忆客 最近更新:2023/02/20 浏览次数:

当我们尝试更改已冻结对象的属性或使用 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”错误的最常见原因是:

  1. 试图将属性分配给冻结的对象或数组。
  2. 使用 Object.defineProperties 时忘记将 writable 设置为 true
  3. 在使用第三方库(例如 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”错误:

  1. 确保在设置属性之前创建冻结对象或数组的副本。
  2. 如果我们使用 Object.defineProperties,请将可写属性设置为 true。
  3. 确保不要修改 React.js 等库中的状态对象,并使用内置方法设置状态。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Do you understand JavaScript closures?

发布时间:2025/02/21 浏览次数:108 分类:JavaScript

The function of a closure can be inferred from its name, suggesting that it is related to the concept of scope. A closure itself is a core concept in JavaScript, and being a core concept, it is naturally also a difficult one.

Do you know about the hidden traps in variables in JavaScript?

发布时间:2025/02/21 浏览次数:178 分类:JavaScript

Whether you're just starting to learn JavaScript or have been using it for a long time, I believe you'll encounter some traps related to JavaScript variable scope. The goal is to identify these traps before you fall into them, in order to av

How much do you know about the Prototype Chain?

发布时间:2025/02/21 浏览次数:150 分类:JavaScript

The prototype chain can be considered one of the core features of JavaScript, and certainly one of its more challenging aspects. If you've learned other object-oriented programming languages, you may find it somewhat confusing when you start

JavaScript POST

发布时间:2024/03/23 浏览次数:96 分类:JavaScript

本教程讲解如何在不使用 JavaScript 表单的情况下发送 POST 数据。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便