问题分类

JavaScript,值引用,地址引用

问题描述

开发过程中,服务端将静态配置数据从mysql数据库中读取到内存中,方便调用。

在实现流派功能时,需从数据库中读取流派种类数据到内存中,由于其中generals字段的值是一个转成了字符串类型的数组,因此需要使用JSON.Parse()解析该字段值,如图:

image.png

 

在实现接口后调用,第一次成功,但是继续请求第二次,就会报错,报错来源是JSON.parse()这里。

 

 

原因分析

从报错信息上看,是JSON.parse的对象类型不正确,导致无法parse,代码中generals的初始值等于'["zhubajie", "sunwukong", "niumowang", "jinjiao", "yinjiao"]',目前是要将该字符串解析成数组,第一次请求时,解析是成功的,但是第二次就失败报错,按设想是,每次请求时,

都取一次内存中的初始配置数据,而初始配置理应是不会变化的,这样保证每次都可以正确解析。

通过代码检查,看到了这段:

(preGeneralGroup[key] as PreGeneralGroup).generals = JSON.parse((preGeneralGroup[key] as PreGeneralGroup).generals);

这里将preGeneralGroup的属性generals重新赋值为数组类型的值,会不会是这里改变了初始配置数据呢?

答案是会的,在JS中,有两种引用方式,一种是值引用,另一种是地址引用,其中:

* 数字、字符串、布尔类型的为原始类型,是值引用

* 数组、对象类型为地址引用

* 值引用 可以深拷贝

* 地址引用 循环到原始类型方可进行深拷贝

而不巧的是我们上面代码中的初始配置就是一个对象,如下图:

PreGeneralGroup类型定义:

image.png

 

因此下面这段代码,实际是地址引用:

let preGeneralGroup: PreGeneralGroupCfg = dataApi.preGeneralGroup.data as PreGeneralGroupCfg;

这就导致了当preGeneralGroup中的属性generals类型被改变时,初始配置dataApi.preGeneralGroup.data对象中的generals属性也被改变了进而导致了报错的产生。

 

解决方案

对需要引用的对象进行深度拷贝,不需要重新造轮子,可以直接使用现有工具包lodash中的cloneDeep()方法即可,如下图:

image.png

 

 
 
 
posted on 2019-12-02 14:51  Boom__Clap  阅读(374)  评论(0编辑  收藏  举报