JS ES新特性之变量的解耦赋值怎么用
小编给大家分享一下JS ES新特性之变量的解耦赋值怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
1.数组的解耦赋值
1.1数组解耦赋值是什么
ECMAScript 2015中允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为 解耦赋值 。
在ECMAScript 2015之前中为变量赋值的方式如下所示:
let a = 1;let b = 2;let c = 3;
在ECMAScript 2015允许写成下面这样。
let [a, b, c] = [1, 2, 3];
ECMAScript 2015
的解耦赋值本质上属于模式匹配。赋值运算符两边的模式相同,左边的变量会被赋予对应位置的值。
1.2数组解耦赋值失败
如果解耦赋值失败的话,变量的值等于 undefined。示例代码如下所示:
// 如果数组的某个索引值的位置的变量,在 = 运算符的右边没有数组中没有对应的索引值与之对应,则解耦赋值失败,其值为 undefinedlet [v] = []let [a, b] = [1]console.log(v, a, b); // undefined 1, undefined
如果想解决解耦赋值失败的问题,需要将其赋值运算符的左右两边的数量保持一致。
1.3不完全解耦赋值
所谓的不完全解耦赋值就是指赋值运算符的右边数组中的数量要大于左边数组中的数量,导致右边数组中的有些变量失效,但是这这种情况下解耦赋值还是会成功的。
示例代码如下所示:
// 赋值运算符左边变量的数量小于右边值的数量let [a, b, c] = [1, 2, 3, 4] // 依然会解耦赋值成功console.log(a, b, c); // 1 2 3
1.4默认值
解耦赋值允许指定默认值的。示例代码如下所示:
let [a = 1, b = 2] = [100]console.log(a, b); // 100 2
在使用默认值的时候值得注意的一点就是,ECMAScript6
内部会使用全等于 === 运算符来判断指定位置的值是否全等于undefined
。只有当 全等于undefined时,其默认值才会生效。
测试代码如下所示:
let [a = 1, b = 2] = [100, undefined]console.log(a, b); // 100 2
当我们使用null值时,虽然null
也表示为空,但是null !== undefined
。所以我们的默认值并不会生效,
测试代码如下:
let [a = 1, b = 2] = [100, null]console.log(a, b); // 100 null
1.5数组解耦赋值的复杂情况
由于JavaScript
是一个弱类型的语言,所以赋值号右边是什么类型都是允许的,那就会出现以下几种特殊情况:
情况一:运算符右边是一个函数,示例代码如下
// 1. 运算符右边是一个函数let [a, b] = [1, function () { return 10;}]console.log(b()); // 10
情况二:运算符右边是一个对象,示例代码如下
// 2. 运算符右边是一个对象let [a, b] = [1, { name: '狐妖小红娘'}]console.log(b); // { name: '狐妖小红娘' }
情况三:运算符右边函数数组,示例代码如下
// 3. 运算符右边是含有数组let [a, b] = [1, [2, 3]]console.log(b); // [ 2, 3 ]
情况四:运算符左右两边都含有数组,示例代码如下所示
// 4. 运算符左右两边都含有数组,示例代码如下所示let [a, [b, c]] = [1, [2, 3]]console.log(b); // 2
2.对象的解耦赋值
对象的解耦赋值是通过变量名称实现与对象的属性名称一一对应实现的。示例代码如下所示:
let { x, y} = { x: 10, y: 20}console.log(x, y); //10 20
值得注意的是赋值运算符两边的格式需要保持一致。
2.1对象解耦赋值的特殊情况
由于 JavaScript
是一个弱类型的语言,所以赋值号右边是什么类型都是允许的,那就会出现以下几种特殊情况:
情况一:运算符右边是一个函数,示例代码如下
// 1. 运算符右边是一个函数let { a, b } = { a: 1, b: function () { return 10; }}console.log(b());// 10
情况二:运算符右边是一个对象,示例代码如下
// 2. 运算符右边是一个对象let {a, b} = { a: 1, b: { name: 'ywanzhou' }}console.log(b); // { name: 'ywanzhou' }
情况三:运算符右边函数数组,示例代码如下
// 3. 运算符右边是含有数组let {a, b} = { a: 1, b: [1, 2]}console.log(b); //[ 1, 2 ]
情况四:运算符左右两边都含有对象,示例代码如下所示
// 4. 运算符左右两边都含有对象let { m: { name, age }, n} = { m: { name: 'test', age: 20 }, n: 20}console.log(name, age); // test 20
2.2解耦赋值失败
如果解耦赋值失败的话,变量的值等于undefined。示例代码如下所示:
// 解耦赋值失败let { a, b} = { a: 10}console.log(b);
2.3不完全解耦赋值
所谓的不完全解耦赋值就是指赋值运算符的右边对象中属性的数量要大于左边对象中属性的数量,导致右边对象中属性的有些变量失效,但是这这种情况下解耦赋值还是会成功的。
// 不完全解耦赋值let { a} = { a: 10, b: 20}console.log(a);
2.4默认值
解耦赋值允许指定默认值的。示例代码如下所示:
// 默认值let { a, b = 100} = { a: 10, b: 20}console.log(b);
3.字符串、数值、和布尔值的解耦赋值
3.1字符串解耦赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
let [h2, y, x] = "一碗周"console.log(h2, y, x, h3); // 一 碗 周
3.2数值和布尔值的解耦赋值
如果直接对数字值/布尔值进行解耦赋值会抛出异常,在对数字值和布尔值进行操作时,其赋值运算符的右边是数值和布尔值,则会先转为对象。
// let [a] = 100; // 抛出异常 描述信息为 TypeError: 100 is not iterable// console.log(a);// 对布尔或者数值进行解耦赋值的话, 需要现将其改变成为对象类型。let { toString: b} = 1;console.log(b === Number.prototype.toString); // truelet { toString: c} = true;console.log(c === Boolean.prototype.toString); // true
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined
和null
无法转为对象,所以对它们进行解构赋值,都会报错。
4.函数的解耦赋值
函数的参数也可以使用解构赋值。示例代码如下所示:
// 使用数组function f([a, b]) { console.log(a, b); }f([10, 20]) // 10 20// 使用对象function fn({ a, b}) { console.log(a, b);}fn({ a: 10, b: 20}) // 10 20
5.小括号的问题
解耦赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。
由此带来的问题是,如果模式中出现小括号怎么处理。ECMAScript 2015
的规则是,只要有可能导致解构的歧义,就不得使用小括号。
但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,建议只要有可能,就不要在模式中放置小括号。
5.1不能使用小括号的情况
如下三种情况不能使用小括号
情况一:变量声明语句,示例代码如下所示
// 如下情况全部会报错let [(a)] = [1];let {x: (c)} = {};let ({x: c}) = {};let {(x: c)} = {};let {(x): c} = {};let { o: ({ p: p }) } = { o: { p: 2 } };
上面6个语句都会报错,因为它们都是变量声明语句,模式不能使用小括号。
情况二:作为函数参数
函数参数也属于变量声明,因此不能带有小括号。
// 报错function f([(z)]) { return z; }// 报错function f([z,(x)]) { return x; }
情况三:赋值语句的模式
// 全部报错({ p: a }) = { p: 42 };([a]) = [5];
上面代码将整个模式放在小括号之中,导致报错。
// 报错[({ p: a }), { x: c }] = [{}, {}];
上面代码将一部分模式放在小括号之中,导致报错。
5.2可以使用小括号的情况
可以使用小括号的情况只有一种:赋值语句的非模式部分,可以使用小括号。
[(b)] = [3]; // 正确({ p: (d) } = {}); // 正确[(parseInt.prop)] = [3]; // 正确
上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的小括号都不属于模式的一部分。第一行语句中,模式是取数组的第一个成员,跟小括号无关;第二行语句中,模式是p,而不是d;第三行语句与第一行语句的性质一致。
6.变量解耦赋值的用处
变量解耦赋值的用处有很多,下面举几个比较常见的例子。
6.1交换变量的值
如果没有解耦赋值交换变量需要借助第三个变量才能完成,示例代码如下所示:
var a = 10, b = 20;var c = a;a = bb = cc = null /// 释放变量console.log(a, b); // 20 10
借助变量解耦赋值完成 ,示例代码如下所示:
let a = 10, b = 20;[a, b] = [b, a]console.log(a, b); // 20 10
使用这种方式不仅简洁,而且易读,语义清晰。
6.2从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
示例代码如下所示:
// 返回一个数组function example() { return [1, 2, 3];}let [a, b, c] = example();// 返回一个对象function example() { return { foo: 1, bar: 2 };}let { foo, bar } = example();
6.3函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。
// 参数是一组有次序的值function f([x, y, z]) { console.log(x, y, z);}f([1, 2, 3]); // 1 2 3// 参数是一组无次序的值function fn({x, y, z}) { console.log(x, y, z);}fn({ z: 3, y: 2, x: 1}); // 1 2 3
6.4提取 JSON 数据
解构赋值对提取 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]
看完了这篇文章,相信你对“JS ES新特性之变量的解耦赋值怎么用”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网行业资讯频道,感谢各位的阅读!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341