ES6 - 基础学习(3): 变量的解构赋值
程序员文章站
2022-03-10 20:36:56
上接 ES6 - 基础学习(3): 变量的解构赋值 函数参数的解构赋值 1、基本用法 function add([x, y]) { return x + y; } console.log(add([1, 2])); // 3 // 如上面代码所示,函数add的形参表面是一个数组,但在实参参数传入时, ......
函数参数的解构赋值
1、基本用法
function add([x, y]) { return x + y; } console.log(add([1, 2])); // 3 // 如上面代码所示,函数add的形参表面是一个数组,但在实参参数传入时,实参数组就被解构并赋值给变量x、y了。当然这些对于函数内部的代码来说,跟参数一个个传入是一样的,反正都只认参数x、y [[1, 2], [3, 4]].map(([a, b]) => a + b); console.log([[1, 2], [3, 4]].map(([a, b]) => a + b)); // [3, 7] 1+2=3,3+4=7 map函数以二维数组内每个成员数组作为参数,进行参数解构,然后计算每个成员数组内参数值之和
2、函数参数的解构也可以使用默认值
// 下面代码中,函数defaultparameter的形参是一个对象(空对象)。通过对这个对象进行解构,得到变量x、y的值,如果解构失败,x、y就等于默认值。 function defaultparameter({x = 0, y = 0} = {}) { console.log([x, y]); return [x, y]; }
defaultparameter({x: 1, y: 2}); // [1, 2] defaultparameter({x: 3}); // [3, 0] defaultparameter({}); // [0, 0] defaultparameter(); // [0, 0] // 注意,下面这种写法会得到不一样的结果。区别在于此处是给参数指定默认值,而不是给变量x、y指定默认值。 // 这两种写法的执行区别是:上一种写法 实参传入函数后,实参对象内没有对应属性的值,则函数参数采用变量已有的默认值进行相关处理,代码依然能正常执行,不会报错。 // 而下一种写法 实参传入函数后,实参对象内没有对应属性的值,则就真没有了,函数参数因为解构赋值操作,无对应属性值的变量就只能等于undefined。这时如果再执行代码,尤其是计算类相关操作,执行就会报错,代码就会中断执行。 function defaultparameter({x, y} = {x: 0, y: 0}) { console.log([x, y]); return [x, y]; }
defaultparameter({x: 1, y: 2}); // [1, 2] defaultparameter({x: 3}); // [3, undefined] defaultparameter({}); // [undefined, undefined] defaultparameter(); // [0, 0] 没有传入参数,函数以默认对象进行解构赋值
// undefined会触发函数参数的默认值。 [1, undefined, 3].map((x = 'yes') => x); console.log([1, undefined, 3].map((x = 'yes') => x)); // [1, "yes", 3]
圆括号问题
解构赋值虽然使用很方便,但是解析起来却不容易。对于编译器来讲,一个式子到底是模式,还是表达式,一开始并不知道,只有等到解析到(或解析不到)等号时才能知道。而由此带来的问题,如果模式中出现圆括号怎么处理。
es6的规则是,只要一个式子中有可能出现解构操作 或 可能让解构操作产生歧义的,就不得使用圆括号。
但是,这条规则实际操作起来却不那么容易辨别,处理起来也相当麻烦。因此,建议在实际开发中,除非很有必要,否则就不要在模式中放置圆括号。
// 以下三种解构赋值不得使用圆括号。 // 变量声明语句,模式不能使用圆括号 let [(a)] = [1]; let {x: (c)} = {}; let ({x: c}) = {}; let {(x: c)} = {}; let {(x): c} = {}; let { o: ({ p: p }) } = { o: { p: 2 } }; // 函数参数也属于变量声明,因此不能带有圆括号 function f([(z)]) { return z; } function f([z,(x)]) { return x; } // 赋值语句的模式 ({ p: a }) = { p: 42 }; // 将整个模式放在圆括号之中,导致报错 ([a]) = [5]; [({ p: a }), { x: c }] = [{}, {}]; // 将一部分模式放在圆括号之中,导致报错
// 可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。 // 下面三行语句圆括号使用正常,代码执行也正确。因为它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。 // 第一行语句中,模式是取数组的第一个成员,跟圆括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质相同。 [(b)] = [3]; ({p: (d)} = {}); [(parseint.prop)] = [3];
解构赋值的用途
变量的解构赋值用途很多
1、变量值交换
let x = 1, y = 2; [x, y] = [y, x]; console.log(x); // 2 console.log(y); // 1
2、函数返回多个值
// js中,一个函数一次只能返回一个值,如果想要返回多个值,则只能将 需要返回的值封装在数组或对象里一起返回,而且返回后取值还是一个麻烦问题。但有了解构赋值,取出这些值就方便很多了。 function returnsarray() { return [1, 2, 3]; // 返回一个数组 } let [a, b, c] = returnsarray(); console.log(a); // 1 console.log(c); // 3 function returnsobject() { return { // 返回一个对象 name: 'es6', description: 'es6解构赋值 补充' }; } let {name, description} = returnsobject(); console.log(name); // es6 console.log(description); // es6解构赋值 补充
3、函数参数的定义
// 解构赋值可以很方便地将一组参数与变量名对应起来。 // 参数是一组有次序的值:数组 function testfunc([x, y, z]) { console.log(x, y, z); // 1 2 3 } testfunc([1, 2, 3]); // 参数是一组无次序的值:对象 function test_func({x, y, z}) { console.log(x, y, z); // 1 2 3 } test_func({z: 3, x: 1, y: 2,});
4、函数参数的默认值
// 参数是一组有次序的值:数组 function testfunc([x = 0, y = 0, z = 0]) { console.log(x + y + z); } testfunc([1, 2]); // 3 实参 少于 形参个数,形参取默认值 testfunc([123, 234, 345]); // 702 实参 等于 形参个数,形参按位置对应取值 testfunc([12, 23, 34, 45]); // 69 实参 多余 形参个数,形参按位置对应取值,多余剩下的不管。 // 参数是一组无次序的值:对象 function test_func({x = 0, y = 0, z = 0}) { console.log(x + y + z); } test_func({x: 1, y: 2}); // 3 实参对象内属性名 与 形参变量名不能一一对应(属性名个数和变量个数不等),未能正确匹配的形参变量 取默认值 test_func({x: 1, y: 2, z: 3}); // 6 实参对象内属性名 与 形参变量名一一对应,形参变量 按名一一对应 取值 test_func({x: 1, y: 2, aa: 4}); // 3 实参对象内属性名 与 形参变量名不能一一对应(属性名个数和变量个数相等),未能正确匹配的形参变量 取默认值
5、提取 json 数据
// 解构赋值对快速提取 json 对象中的数据,尤其有用。 let jsondata = { name: 'es6', description: 'es6解构赋值 补充', time: [2015, 6] }; let {name, description, time: number} = jsondata, [year, month] = number; console.log(name); // es6 console.log(description); // es6解构赋值 补充 console.log(year); // 2015 console.log(month); // 6
6、获取 set 数据结构内数据、 遍历 map 数据结构
// set数据结构是es6新增的一种数据结构,是一种类数组 数据结构,只是set结构实例内各个成员是唯一的,不允许重复。 // map则是es6新增的另一种数据结构,是一种类对象 数据结构,同样map实例内的属性也不允许重复,而且map结构内 属性字段不限数据类型。 // 任何部署了 iterator接口的对象,都可以用 for...of 循环遍历。map结构原生支持 iterator接口,配合变量的解构赋值,可以更方便的获取键名和键值。 let tempset = new set([1, 2, 'name', 'description']); console.log(tempset); // set(4) {1, 2, "name", "description"} let [a, b, c, e] = tempset; console.log(a); // 1 console.log(b); // 2 console.log(c); // name console.log(e); // description let tempmap = new map(); tempmap.set('name', 'es6').set('description', 'es6解构赋值 补充'); for (let [key, value] of tempmap) { console.log(key + " is " + value); } // 若只想获取键名,或只想获取键值,都可以。 for (let [key] of tempmap) { console.log(`键名: ${key}`); // 遍历键名 } for (let [, value] of tempmap) { console.log(`键值: ${value}`); // 遍历键值 }
7、输入模块的指定方法
加载其他模块时,如果不想加载整个模块,则可以通过解构赋值的方式指定输入要加载的方法,从而既可以减少依赖加载,又可以使得输入语句清晰明了。
const {sourcemapconsumer, sourcenode} = require("source-map");
下一篇: 教你用JAVA写文本编辑器(四)