Cannot assign to read only property ‘0’ of string的报错原因之一及解决办法

一. 需求场景

现有项目,需要对提交资料的人员进行审核,审核不过的时候向服务器提交数据,数据结构中的certificationStatus需为JSON格式
1.1 资料信息结构如下:
 auditFailedInfor: {
   id: null, 
   type: null, 
   certificationStatus: { 
      practiceCardSt: 1, 
      identityCardSt: 1, 
      positionCardSt: 1, 
   }, 
   doctorNameSt: 1, 
   failDetails: null
 }
1.2 当用户资料审核不过时,将数据传给服务器

将auditFailedInfor中的certificationStatus数据转为JSON格式

if (this.auditFailedInfor.type === 1) {
   this.auditFailedInfor.certificationStatus = JSON.stringify(this.auditFailedInfor.certificationStatus)
}

调用封装好的请求函数,将该用户所有数据发送给服务器保存

certificationAuditFail(this.auditFailedInfor)

提交数据成功以后,需要将this.auditFailedInfor里面的数据置为默认值,不然会影响下一个人员的审核。对于certificationStatus来说,也就是需要将它里面的值改为默认值1

for(let item in this.auditFailedInfor.certificationStatus) {
   this.auditFailedInfor.certificationStatus[item] = 1
}

二. 报错场景

以上代码,我成功提交了上个审核不过人员的资料,但在点击审核下一个人的数据时报错了,如下:
在这里插入图片描述

2.1 报错原因
auditFailedInfor.certificationStatus数据在转为JSON前是一个object,转换了之后变成了string,所以我在对auditFailedInfor.certificationStatus进行for in操作将数据重置为初始值的时候就报了上面的错。

三. 解决办法

第一种方法: 在向服务器发送请求前,先将auditFailedInfor数据赋值给另外一个变量(例:赋值给submitAuditFailedInfor ),然后对submitAuditFailedInfor进行转JSON之类的操作,这样在重置初始值的时候,用的是auditFailedInfor,那么auditFailedInfor.certificationStatus依然是个对象,就不会报错。

第二种方法: 在重置初始值之前,先将auditFailedInfor.certificationStatus从字符串转换为对象。
3.1 我采用的第一种解决办法

在向服务器发送数据前,我进行了如下操作:

1.将this.auditFailedInfor数据赋值给一个新的变量

let submitAuditFailedInfor = this.auditFailedInfor

2.将certificationStatus数据转为JSON格式

if (submitAuditFailedInfor.type === 1) {
   submitAuditFailedInfor.certificationStatus = JSON.stringify(submitAuditFailedInfor.certificationStatus)
}

3.将数据发送给服务器保存

certificationAuditFail(submitAuditFailedInfor)

4.重置初始值

for(let item in this.auditFailedInfor.certificationStatus) {
   this.auditFailedInfor.certificationStatus[item] = 1
}

成功提交了上个审核不过人员的资料,但在点击审核下一个人的数据时又报错了,如下:
在这里插入图片描述
黑人问号脸?怎么又是你?

3.2 分析原因

思考了之后,我找到了问题的所在,auditFailedInfor数据是一个深层嵌套对象,而我下面这个操作是浅拷贝。

let submitAuditFailedInfor = this.auditFailedInfor

也就是说submitAuditFailedInfor.certificationStatus 和 auditFailedInfor.certificationStatus依然是共用一个地址,任意改变一个就会影响到另一个发生相同的改变。所以应该用深拷贝的方法,于是进行了如下操作:

let submitAuditFailedInfor = Object.assign({}, this.auditFailedInfor) 

照着3.1上面的流程走了一遍以后就没有再报错了,成功解决了问题。

四. 分析该报错具体原因

4.1 以上我犯了两点错误:

第一点: 在使用某个方法的时候,没有考虑使用者的类型是不是可以使用该方法。

第二点: 在对数据进行拷贝的时候,没有先分析数据类型再选择方法,而是采用直接赋值的形式。

4.2 造成Cannot assign to read only property ‘0’ of string报错的实际原因:(该例中对JSON字符串进行for..in操作)

☆ 当你用的方法不属于string数据类型的时候就会报该错,所以在报该错的时候,你需要检查你使用的方法是不是string拥有的方法,一层层往上查。

☆ 比如4.2中第二点,我将auditFailedInfor赋值给新变量submitAuditFailedInfor,在我看来auditFailedInfor中的certificationStatus就应该还是原来的对象,所以可以使用for...in的方法;然而因为直接赋值是浅拷贝,数据共用一个地址,修改就会相互影响,所以auditFailedInfor中的certificationStatus数据也变成了JSON对象,那么使用for...in时就继续报了该错。

讨论数量: 0

慎思笃行