首页
留言
关于
友链
更多
足迹
实验室
地图组件
Search
1
SpringMVC+Spring+MyBatis整合完整版Web实例(附数据)
2,647 阅读
2
关于在Flutter实现Google地图的方法
1,127 阅读
3
SqlServer分组排序后取第一条记录
723 阅读
4
Maven仓库报错:Could not transfer artifact org.springframework.boot:spring-boot-maven-plugin:pom···
645 阅读
5
druid报异常 “sql injection violation, part alway true condition not allow”的解决方案
619 阅读
发现
技术
生活
户外
登录
Search
标签搜索
Git
JavaScript
Oracle
Git学习
Java
Flutter
MySQL
SQL Server
Spring Boot
Flutter 2.0
对称加密算法
IntelliJ IDEA
Google地图
Maven
ES6
秦岭户外
linux
Tomcat
Redis
Spring
Bai Keyang
累计撰写
270
篇文章
累计收到
275
条评论
首页
栏目
发现
技术
生活
户外
页面
留言
关于
友链
足迹
搜索到
1
篇与
函数参数解构赋值
的结果
2022-02-04
ES6之变量的解构赋值(Destructuring)
ES6中解构赋值主要分为6类,分别为 数组解构赋值 、对象解构赋值 、字符串解构赋值 、数值和布尔值解构赋值 、函数参数解构赋值 。什么是解构?在ES6中允许按照一定的模式从数组和对象中提取值,然后对变量进行赋值,这被称为解构(Destructuring)数组解构赋值数组的解构赋值时,等号的右边必须是数组,否则将会报错。只要数据结构具有Iterator借口,则都可以采用数组形式的解构赋值。let [a, b, c] = [1, 2, 3]; a // 1 b // 2 c // 3这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些常见的解构例子:let [f, [[k], y]] = [1, [[2], 3]]; f // 1 k // 2 y // 3 let [ , ,t] = ["php", "java", "go"]; t // go let [x, ,y] = ["php", "java", "go"]; x // php y // go let [k, ...t] = [1, 2, 3, 4]; k // 1 t // [2, 3, 4] let [x, y, ...z] = ["php"]; x // php y // undefined z // []当解构不成功,变量的值就等于undefined。下面代码中,f均解构不成功,为undefined。let [f] = []; let [k, f] = [1];Set结构也可以使用数组的解构赋值,如下:let [x, y, z] = new Set(["php", "java", "go"]); x // php y // java z // go还有一种情况是部分解构成功,如下:let [x, y] = [1, 2, 3]; x // 1 y // 2 let [a, [b], c] = [1, [2, 3], 4] a // 1 b // 2 c // 4以上情况是不完全解构,即等号左边的模式只能匹配一部分等号右边的数组。但是这种情况下,结构依然可以成功。let [f] = 1; let [f] = false; let [f] = NaN; let [f] = undefined; let [f] = null; let [f] = {};以上语句都会报错,因为等号右边的值或是转为对象以后不具备iterator接口(前五个表达式),或是本事就不具备Iterator接口(最后一个表达式)数组解构赋值中允许指定 默认值 ,如:let [f = true] = []; f // true let [a, b = 'x'] = ['y']; a // y b // x let [a, b = 'c'] = ['k', undefined]; a // k b // c let [x = 1] = [undefined]; x // 1 let [x = 1] = [null]; x // null let [x = 1, y = x] = []; // x = 1, y = 1 let [x = 1, y = x] = [2]; // x = 2, y = 2 let [x = 1, y = x] = [1, 2]; // x = 1, y = 2 let [x = y, y = 1] = []; // 报错:ReferenceError最后一个表达式之所以报错,是因为x引用了默认值y时,y还没有被声明。注:ES6内部使用严格相等运算符(===)判断一个位置是否有值。如果一个数组成员不严格等于undefined,默认值是无法生效的。对象解构赋值对象的解构与数组有一个重要的不同:数组的元素是按次序排列的,变量的取值是由它的位置决定的;而对象的属性没有次序,变量必须与属性同名才能取到正确的值。示例如下:let {f, b} = {f: "AA", b: "KK"}; // f --> AA b --> KK let {c} = {f: "AA", b: "KK"}; // c --> undefined如果变量名与属性名不一致,必须用如下的形式:let {f: b} = {f: 'AA', b: 'CC'}; // b --> AA let obj = {hello: 'AA', world: 'CC'}; let {hello: h, world: w} = obj; // h --> hello w --> world hello --> error: hello is not defined对象的解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量。真正被赋值的是后者,而不是前者。对象解构也可以指定默认值:let {x = 3} = {}; // x --> 3 let {x, y = 5} = {x: 1}; // x --> 1 y --> 5 let {x : y = 3} = {}; // y --> 3 let {x : y = 3} = {y : 5}; // y --> 5 let {x = 3} = {x : undefined}; // x --> 3 let {x = 3} = {x : null}; // x --> null默认值生效的条件是对象的属性值严格等于undefined如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错,如下:let {f: {bo}} = {bc: "bucc"}以上代码报错的原因是因为f此时等于undefined,再取子属性就会报错。如果将一个已经声明的变量用于解构赋值,必须非常小心。 常见的错误如下:// 错误的写法 let x; {x} = {x : 1}; // SyntaxError: syntax error // 正确的写法 let x; ({x} = {x : 1});以上代码中第一部分会报错,是因为JavaScript引擎会将{ x }理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。解构赋值允许等号左边的模式之中不放置任何变量名。虽然此类表达式毫无意义,但是语法合法,且可以正常执行:({} = [true, false]); ({} = 'abc'); ({} = []);由于数组本质是特殊的对象,因为可以对数组进行对象属性的解构:let arr = [1, 2, 3]; let {0: first, [arr.length - 1]: last} = arr; // first --> 1 last --> 3字符串解构赋值字符串在进行解构赋值时,字符串被转换成了一个类似数组的对象:let [a, b, c, d, e] = 'hello'; // a -->h a -->e a -->l a -->l a -->o类似数组的对象都有一个length的属性,因为还可以对这个属性进行解构赋值:let {length : len} = 'hello'; // len --> 5数值和布尔值解构赋值在数值和布尔值解构赋值时,如果等号右边是数值或布尔值,则会先转为对象。let {toString:s} = 123; s === Number.prototype.toString; // true let {toString:s} = true; s === Boolean.prototype.toString; // true解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。let {prop: x} = undefined; // TypeError let {prop: y} = null; // TypeError函数参数解构赋值函数的参数也可以使用解构赋值。function add([x, y]) { return x + y; } add([3, 2]); // 5 [[1,2],[3,4]].map(([a, b]) => a + b); // [3, 7]函数参数的解构也可以使用默认值:// 示例一 function move ({x = 0, y = 0} = {}) { return [x, y] } move({x: 3, y: 9}); // [3, 9] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0] // 示例二 function move({x, y} = {x : 0, y : 0}) { return [x, y]; } move({x: 3, y: 9}); // [3, 9] move({x: 3}); // [3, undefined] move({}); // [undefined, undefined] move(); // [0, 0]关于圆括号的问题解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。ES6规则是只要有可能导致解构的歧义,就不得使用圆括号。但是这个在实际中并不那么容易判断,且处理起来相当的麻烦。所以也建议,只要有可能就不要在模式中放置圆括号。不能使用圆括号的情况情况一:变量声明语句let [(a)] = [1]; // 错误 let {x : (c)} = {};// 错误 let ({x : c}) = [1];// 错误 let {(x : c)} = [1];// 错误 let {(x) : c} = [1];// 错误 let {o : ({p:p})} = {o: {p: 2}};// 错误类似以上代码语句都会报错,因为它们都是变量声明语句,模式不能使用圆括号。情况二:函数参数函数参数也属于变量声明,因此不能使用圆括号function f ([(z)]) { return z; }// 错误 function f ([z, (x)]) {return x; }// 错误情况三:赋值语句的模式// 将整个模式放入圆括号之中导致报错 ({p : a}) = {p: 4};// 错误 ([a]) = [5];// 错误 // 将一部分模式放入圆括号之中导致报错 [({p: a}), {x: c}] = [{}, {}];// 错误可以使用圆括号的情况可以使用圆括号的情况只有一种:赋值语句的非模式部分可以使用圆括号。[(b)] = [3]; // 正确 ({p: (d)} = {});// 正确 [(parseInt.prop)] = [3];// 正确以上三个语句均执行正确,因为他们的都是赋值语句,而不是声明的语句,另外它们的圆括号都不属于模式的一部分。用途变量的解构赋值用途很多:交换变量的值let x = 1; let y = 2; [x, y] = [y, x];从函数返回多个值函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里面返回。// 返回一个数组 function test1() { return [1, 2, 3]; } let [a, b, c] = test1(); // 返回一个对象 function test2() { return { a: 2, b: 6 }; } let {a, b} = test2();函数参数的定义解构赋值可以方便的将一组参数与变量名对应起来// 参数是一组有序的值 function f1([x, y, z]) { ... } f1([1, 2, 3]); // 参数是一组无序的值 function f2({x, y, z}}) { ... } f2({z: 8, x: 6, y: 4});提取JSON数据let jsonData = { id: 2, name: 'LiMing', data: [867, 22] } let {id, name, data: nums} = jsonData; console.log(id, name, nums); // 2, "LiMing", [867, 22]函数参数的默认值jQuery.ajax = function (url, { async = true, cache = true, complate = function(){} }) { // do stuff } 遍历Map结构任何部署了Iterator接口的对象都可以用for...of 循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值获取键名和键值就非常方便。let map = new Map(); map.set('one', 'hello'); map.set('two', 'world'); for(let [key , value] of map) { console.log(key, value); } // 获取键名 for(let [key] of map) { console.log(key); } // 获取键值 for(let [, value] of map) { console.log(value); }输入模块的指定方法:加载模块时往往需要指定输入的方法。解构赋值使得输入语句非常清晰:const {SourceMapConsumer, SourceNode} = require("source-map");
2022年02月04日
63 阅读
0 评论
0 点赞