关于js中对象的嵌套的解构并重组
在看《你不知道的JavaScript》下卷的时候遇到了一个问题,在第二部分2.5.3中的解构并重组遇到了一段代码
var defaults = {
options: {
remove: true,
enable: false,
instance: {}
},
log: {
warn: true,
error: true
}
}
var config = {
options: {
remove: false,
instance: null
}
}
我们的本意是想要把config和defaults中的数据合并,并保留config自带的参数,虽然可以通过Object.assign来实现,但是因为是浅操作的原因,会导致内部对象比如options等只会复制对象引用,所以作者提供了一个结构的函数
config.options = config.options || {};
config.log = config.log || {};
{
options: {
remove: config.options.remove = defaults.options.remove,
enable: config.options.enable = defaults.options.enable,
instance: config.options.instance = defaults.options.instance
} = {},
log: {
warn: config.log.warn = defaults.log.warn,
error: config.log.error = defaults.log.error
} = {}
} = config
但是这样就出现了一个问题,就是这么写的话会报错
Uncaught SyntaxError: Unexpected token ‘:’
记得前面有讲过说在解构赋值的时候{ }不可以直接出现在等号的左侧,不然会被当做语句块处理而不是对象处理
于是我加上了一个var变成了这样
var {
options: {
remove: config.options.remove = defaults.options.remove,
enable: config.options.enable = defaults.options.enable,
instance: config.options.instance = defaults.options.instance
} = {},
log: {
warn: config.log.warn = defaults.log.warn,
error: config.log.error = defaults.log.error
} = {}
} = config
这样总没问题了吧?
Uncaught SyntaxError: Illegal property in declaration context
oh no ! 还是报错了,大概意思是使用了非法属性(我也没能理解为什么会报这个错,看看有没有大佬解答一下)
在vscode中报错(期望的符号应该是 , 而不是 . )
‘,’ expected
然后我想了想这个语法,按照正常来说,应该是声明变量的时候使用解构赋值,从config之中解构出options和log,然后再从这里面解构出几个属性,并且赋值给了config.options和config.log
啊?这是可以用var声明的吗,比如这么写
var a = {}
var a.haha = 123
Uncaught SyntaxError: Unexpected token ‘.’
哎!报了一样的错误,说明是不可以这样赋值的
不知道是不是这个书出的年代太久远了,版本更新已经不允许这么写了,于是我就试了另一个写法
var a = {
options: {
remove: config.options.remove = defaults.options.remove,
enable: config.options.enable = defaults.options.enable,
instance: config.options.instance = defaults.options.instance
} = {},
log: {
warn: config.log.warn = defaults.log.warn,
error: config.log.error = defaults.log.error
} = {}
} = config
在控制台中输入a和config的数据,发现都变化了(并且符合我们的预期),并且最最最重要的一点!!!就是 a === config 的返回值是true。
那么这样就符合预期了,我就开始分析为什么会这样,以下都是个人推测和理解,有错误希望大佬指出:
首先我们通过“var a =”这些附加品解决了前面遇到的两个报错的问题,回到了正常的结构赋值的问题
首先我们从config中解构出了options和log
然后我们再从opitons和log中解构出了remove,enable等属性
解构赋值中的结构是source -> target的哦不要搞错了
然后我们将remove等属性都一一赋值到了config.options和config.log上
而config原本没有的属性例如log中的warn和error,我们就会使用defaults.log的对应属性(解构赋值的默认值)
然后又有重点来啦!!!
在解构赋值采用了默认值之后,其实进行了两步:这里我们拿warn: config.log.warn = defaults.log.warn来举例子
- 首先我们发现从config.log中解构出来的结果中是没有warn的,那么就会取得默认值也就是defaults.log.warn
- 然后warn就有值了,并且把这个值传给了config.log.warn。
那么我们就实现了结构赋值的同时,把config重组了
在控制台输出config我们就会发现他是已经达到了我们的预期,也就是作者想要表达的意思!
那为什么a === config呢?
我猜应该是赋值链最右端的值会一直往左边传吧,所以相当于进行了一步a = config,而config是对象,也就会进行一个浅拷贝咯
以上都是个人测试和理解,有错误希望大佬指出!!