文章目录
1、什么是解构赋值
解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量。
- 版本支持
ES6+
- 阮大:
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
2、 为什么会出现解构
写过js的人一定对以下代码很熟悉吧
let data ={ a:1, b:2, c:3 } let a1 = data.a let b1 = data.b let c1 = data.c console.log(a1,b1,c1)
- 打印结果为:
1 2 3
偶尔写一两次没什么,但是写久了,你就会觉得它重复臃肿,不够优雅。
那么有没有什么办法可以解决呢?
- 解构赋值:有有有,我来拯救你来了!请看一下,借助我重构上面的代码的结果吧。
const { log } = console let [a,b,c] = [1,2,3] log(a,b,c)
- 打印结果也为:
1 2 3
- 但是是不是觉得优雅了许多呢。
到此为止,你是否也对解构充满了好奇呢?且听我为你娓娓道来吧
3、解构赋值的类型
3.1 数组的解构赋值
类似于以下代码模式其实就是最简单的一种数组解构赋值
let [a,b,c] = [1,2,3]
- 那么还有没有什么骚操作呢,答案是肯定有的
- 比如说,你从数据库拿到了一个列表,但是只要里面的第三,第四个对象,那么我们也可以这么操作
let data = [ 1,2,3,4,5,6,7,8,9 ] let [ , , d3, d4] = data // 第一第二个值直接不接收 console.log(d3,d4)
- 好了,对数组的骚操作就不做过多展示了,因为在实际开发中,用到最多的还是
对象的解构
,下面一起来看看吧。
3.2 对象的解构赋值
比如说第一个例子里面的
const { log } = console
就是一种对象的解构,声明了log
之后,就可以直接使用log
代替console.log
了,那么我们的输出也会变得跟C语言的printf
一样一个关键字就可以输出,可以加快开发速率。
- 借用第一个例子里面的
data
,如果我们拿到的是一个data对象,又应该如何快速使用数据(拿到对象里面a, b, c
的数字)。
let data ={ a:1, b:2, c:3 }
- 在没有学解构之前你可能是这么做的
const a = data.a const b = data.b const c = data.c
- 但是学了解构之后,你可能是这么做的
const { a, b, c } = data
是不是觉得很高大上,很优雅
PS:此处应有掌声!!!
小明:数组都可以这么骚,你怎么不骚一点呢?
对象解构:你在怀疑我的能力吗?看好咯,下面我要开大招了(后面部分不演示旧的做法啦)
- 如果对象里面有嵌套,我们要怎么同时获得嵌套以及非嵌套数据呢?
比如说data变成了这样(如下),要怎么同时拿到a, b, c 以及name, age
的值呢?
let data ={ a:1, b:2, c:3, obj:{ name:'TOM', age:18 } }
- 不用解构
const a = data.a const b = data.b const c = data.c const na = data.obj.name const age = data.obj.age
- 使用解构
const { a, b, c, obj:{ name, age } } = data
- 强烈建议自己模仿一遍,那种感觉简直不要太爽
- 如果嵌套层数更深呢?
还是变一下data
const { log } = console let data ={ a:1, b:2, c:3, obj:{ name:'TOM', age:18, child:{ name:'hello', age:1, mother:{ name:"mama" } } } }
这个时候如果我们想拿到a,b,c以及child里面的mother的name
的话操作好办。直接
const { a, b, c, obj:{ child: { mother} } } = data
这样就完事了。
但是如果我们想要a,b,c,obj里面的name,age以及里面child里面的name,age或者mother里面的name
的话,如果还是像上面那样操作的话,你就会发现有重名的了,编译器也会报错
name, ^ SyntaxError: Identifier 'name' has already been declared
那么该如何解决这个问题呢。
- 直接使用老的方法,一个一个点出来
比如拿
mother里面的name
const na = data.obj.child.mother.name
- 解构的时候使用别名
const { a, b, c, name:na1, age:ag1, obj:{ name:na2, age:ag2, child: { name: na3, age: ag3, mother : { name:na4 } } } } = data log( a,b,c, na1, na2, na3, na4 ) // 结果: 1 2 3 undefined TOM hello mama
na1
打印undefined
的原因是data
的最外层没有name
属性,所以解构失败了
小明:这么骚!老铁666
这个时候如果我们只想要a跟mother的name
就可以这样(如下),因为没有重名,所以不用别名也可以编译通过。
const { a, obj:{ child: { mother : { name } } } } = data
3.3 函数参数的解构赋值
- 在使用解构之前,我们的函数一般会这样写
const { log } = console function f(x,y){ log(x,y) } f(3,8)
但是这样写的话,注定了参数的自由很少(所传的参数必须有序)
- 因为我们学了解构,所以我们可以直接传一个对象,那就方便很多了
function f(obj){ let { name, age } = obj log(name, age) } f( { name:'xiaoming', age:18 } )
- 考虑程序的容错性,我们还可以给函数参数一些默认值
function f( obj={ name:'默认姓名', age:18 } ){ let { name, age } = obj log(name, age) } f( { name:'xiaoming', age:18 } ) f()
结果:
xiaoming 18 默认姓名 18
3.4其他的解构可以参考阮大的文章
4、解构的用途
这一部分转载自阮大的ES6教程,因为写的真的太好了,转载下来,方便自己复习
手动狗头:害怕阮大的网站被坏银攻击看不到就亏大了
[附阮大的详细教程网址](变量的解构赋值 - ECMAScript 6入门 (ruanyifeng.com))
(1)交换变量的值
let x = 1; let y = 2; [x, y] = [y, x];
上面代码交换变量x
和y
的值,这样的写法不仅简洁,而且易读,语义非常清晰。
(2)从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
// 返回一个数组 function example() { return [1, 2, 3]; } let [a, b, c] = example(); // 返回一个对象 function example() { return { foo: 1, bar: 2 }; } let { foo, bar } = example();
(3)函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。
// 参数是一组有次序的值 function f([x, y, z]) { ... } f([1, 2, 3]); // 参数是一组无次序的值 function f({x, y, z}) { ... } f({z: 3, y: 2, x: 1});
(4)提取 JSON 数据
解构赋值对提取 JSON 对象中的数据,尤其有用。
let jsonData = { id: 42, status: "OK", data: [867, 5309] }; let { id, status, data: number } = jsonData; console.log(id, status, number); // 42, "OK", [867, 5309]
上面代码可以快速提取 JSON 数据的值。
(5)函数参数的默认值
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, complete = function () {}, crossDomain = false, global = true, // ... more config } = {}) { // ... do stuff };
指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';
这样的语句。
(6)遍历 Map 结构
任何部署了 Iterator 接口的对象,都可以用for...of
循环遍历。Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。
const map = new Map(); map.set('first', 'hello'); map.set('second', 'world'); for (let [key, value] of map) { console.log(key + " is " + value); } // first is hello // second is world
如果只想获取键名,或者只想获取键值,可以写成下面这样。
// 获取键名 for (let [key] of map) { // ... } // 获取键值 for (let [,value] of map) { // ... }
(7)输入模块的指定方法
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");
5、状态:未完待续。。。。
原作不易,这不给个一键三连吗?