ES6 解构赋值详解

解构赋值是对赋值运算符的扩展,可以将属性/值从对象/数组中取出,赋值给其他变量。

 

一、数组的解构赋值

1、基本用法

只要等号两边的模式相同,左边的变量就会被赋予对应的值。

let [a, [[b], c]] = [1, [[2], 3]];
a // 1
b // 2
c // 3
let [a, , c] = [1, 2, 3]; a // 1 c // 3
let [a, ...c] = [1, 2, 3, 4]; a // 1 c // [2, 3, 4]

let [a, b, ...c] = [1]; a // 1 b // undefined c // []

解构赋值不仅适用于 let 命令,也适用于 var 和 const 命令。

 

2、默认值

解构赋值允许指定默认值。

var [a = 1] = [];
a  // 1

[a, b = 2] = [1];
a  // 1
b  // 2

[a, b = 2] = [1, undefined];
a  // 1
b  // 2

由于 ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于 undefined,默认值是不会生效的。

var [a = 1] = [undefined];
a // 1

var [a = 1] = [null]; a // null

上面代码中,如果一个数组成员是 null,默认值就不会生效,因为 null 不严格等于 undefined。

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

let [a = 1, b = a] = [];
a // 1
b // 1

let [a = 1, b = a] = [2];
a // 2
b // 2

let [a = 1, b = a] = [1, 2];
a // 1
b // 2

let [a = y, b = 1] = [];
// ReferenceError

上面最后一个表达式之所以会报错,是因为a用到默认值b时,b还没有声明。

 

二、对象的解构赋值

1、基本用法

解构不仅可以用于数组,还可以用于对象。

var { a, b } = { a: "aaa", b: "bbb" };
a // "aaa"
b // "bbb"

对象解构与数组结构的区别:

  • 数组的元素是按次序排列的,变量的取值由它的位置决定;
  • 而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
var { a, b } = { b: "bbb", a: "aaa" };
b // "bbb"
a // "aaa"

var { c } = { a: "aaa", b: "bbb" }; c // undefined

如果变量名与属性名不一致,则需要这样写:

var { a: x } = { a: "aaa", b: "bbb" };
x // "aaa"

let obj = { a: "aaa", b: "bbb" }; let { a: x, b: y } = obj; x // "aaa" y // "bbb"

对象解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而非前者。

所以上面第二个代码如果直接输出a或b则会报错:

let obj = { a: "aaa", b: "bbb" };
let { a: x, b: y } = obj;
a // error: a is not defined
b // error: b is not defined

上面代码中,真正被赋值的是变量x和y,而非模式a和b

注意,对于 let 和 const 来说,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错。

let a;
const obj = { a:"aaa" };
{a} = obj;
a // SyntaxError: Unexpected token =

解决方法:在第二行代码加上“()”

let a;
const obj = { a:"aaa" };
({a} = obj);
a // "aaa"

上面代码中,解析器会将起首的大括号,理解成一个代码块,而非赋值语句。

和数组一样,解构也可以用于嵌套结构的对象。

var obj = {A: {a: {x: 1,}}
};
var { A: { a: { x }} } = obj;
A // undefined
a // undefined
x // 1

上面代码中,只有x是变量,A和a都是模式,不会被赋值。

 

2、默认值

对象的解构也可以指定默认值。

var {a = 1} = {};
a // 1

var {a, b = 2} = {a: 1}; a // 1 b // 2
var { a: x = 1 } = {}; x // 1

默认值生效的条件是,对象的属性值严格等于undefined。

var {a = 1} = {a: undefined};
a // 1

var {a = 3} = {a: null}; a // null

如果将大括号写在行首,JavaScript 会将其解释为代码块。

var x;
{x} = {x: 1};
// SyntaxError: syntax error

上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。

//  解决方法
({x} = {x: 1});

 

三、字符串的解构赋值

字符串也可以解构赋值,因为字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "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

上面代码中,数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。

解构赋值的规则是,只要等号右边的值不是对象,就先将其转为对象。

由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

let { prop: x } = undefined; // TypeError

let { prop: y } = null; // TypeError

 

五、函数参数的解构赋值

函数的参数也可以使用解构赋值。

function add([x, y]){
return x + y;
}
add([1, 2]); // 3

函数参数的解构也可以使用默认值。

function iPhone(a = "x", b = "A11", c = "1200"){console.log(a, b, c);
}
iPhone("xs","A12"); // xs A12 1200

 

六、圆括号问题

1、不能使用圆括号的情况

( 1 )变量声明语句中,不能带有圆括号。

//  全部报错
var [(a)] = [1];
var {x: (c)} = {};
var ({x: c}) = {};
var {(x: c)} = {};
var {(x): c} = {};
var { o: ({ p: p }) } = { o: { p: 2 } };

( 2 )函数参数中,模式不能带有圆括号。

//  报错
function f([(z)]) { return z; } 

( 3 )赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号之中。

//  全部报错
({ p: a }) = { p: 42 };
([a]) = [5];
  • 上面代码将整个模式放在圆括号之中,导致报错。

 

2、可以使用圆括号的情况

  • 可以使用圆括号的情况只有一种:赋值语句的非模式部分
[(b)] = [3]; //  正确
({ p: (d) } = {}); //  正确
[(parseInt.prop)] = [3]; //  正确
  • 上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;
  • 其次它们的圆括号都不属于模式的一部分。
  • 第一行语句中,模式是取数组的第一个成员,跟圆括号无关;
  • 第二行语句中,模式是 p ,而不是 d ;
  • 第三行语句与第一行语句的性质一致.

 

七、解构赋值的应用

1、交换变量的值

[x, y] = [y, x];
// 交换变量x和y的值

 

2、从函数返回多个值

//  返回一个数组
function arr() {return [1, 2, 3];
}
var [a, b, c] = arr();
// 返回一个对象 function obj() {return {a: 1,b: 2}; } var { a, b } = obj();

 

3、函数参数的定义

//  参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值 function f({x, y, z}) { ... } f({z: 3, y: 2, x: 1});

 

4、提取 JSON 数据

var jsonData = {id: 42,status: "OK",data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]

 

转载于:https://www.cnblogs.com/Leophen/p/11179027.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件著作权申请流程

一、填写计算机软件著作权登记申请表(表格1份)包括软件全称、简称、版本号、开发完成日期、软件开发情况(独立开发、合作开发、委托开发、下达任务开发)、原始取得权利情况、继受取得权利情况、权利范围、软件用途和技术特点&…

Npm install failed with “cannot run in wd”

Linux环境下,root账户,安装某些npm包的时候报下面的错误,例如安装grunt-contrib-imagemin时: Error: EACCES, mkdir /usr/local/lib/node_modules/coffee-scriptnpm ERR! { [Error: EACCES, mkdir /usr/local/lib/node_modules/c…

Java EE 7 Batch中传递属性/参数的2种方式

对于Java EE 7批处理工具,有两种将属性/参数传递给块和批处理的方法。 本快速指南向您展示了两种方式,在开发批处理Java EE 7方式时可能会经常使用它们。 1.运行前预定义的属性/参数 预定义属性是您在部署应用程序之前定义的属性(名称/值对&…

Csharp 打印Word文件默認打印機或選擇打印機設置代碼

//打印文檔object nullobj Missing.Value;//aDoc wordApp.Documents.Open(ref file,// ref nullobj, ref nullobj, ref nullobj,// ref nullobj, ref nullobj, ref nullobj,// ref nullob…

ESLint共享配置的两种方式eslint-plugin和eslint-config

使用ESLint很久了,也看了ESLint官方文档很多遍,但对于ESLint配置的规则还是不胜清楚,例如: {"extends": ["plugin:prettier/recommended"] }上面extends的值为什么要"plugin:"开头?这里…

使用aggregate在MongoDB中查找重复的数据记录

我们知道,MongoDB属于文档型数据库,其存储的文档类型都是JSON对象。正是由于这一特性,我们在Node.js中会经常使用MongoDB进行数据的存取。但由于Node.js是异步执行的,这就导致我们无法保证每一次的数据库save操作都是原子型的。也…

Gradle入门:创建二进制分发

创建有用的应用程序之后,很可能我们想与其他人共享它。 一种方法是创建一个可以从我们的网站下载的二进制发行版。 这篇博客文章描述了如何满足以下要求的二进制发行版: 我们的二进制分发绝对不能使用所谓的“胖子”方法。 换句话说,我们的…

我的Google Adsense帐户被关

一、 上周四,我收到Google的邮件,宣布关闭我的Adsense帐户。 "您好! 查看了相关记录后,我们确认您的 AdSense 帐户存在引起无效活动的风险。保护 AdWords 广告客户,使其免受无效活动的侵害是我们的责任&#xff0…

网格布局之网格元素放置算法

接下来的网格元素放置算法将网格元素的自动位置解析为确定位置,确保每个网格元素具有布局明确的网格区域。(Grid spans 不需要特别的解析;如果没有明确指定,默认是1) 注意:当显式网格中没有位置放置自动放置…

csharp: ODP.NET,System.Data.OracleClient(.net 4.0) and System.Data.OleDb读取Oracle g 11.2.0的区别...

ODP.NET: 引用: using Oracle.DataAccess; //Oracle g 11.2.0 using Oracle.DataAccess.Client; using Oracle.DataAccess.Types; //下载 http://www.oracle.com/technetwork/topics/dotnet/downloads/net-downloads-160392.html //引用:D:\app\geovindu…

AngularJS快速入门指南15:API

API即Application Programming Interface(应用程序接口)。 AngularJS全局API AngularJS全局API是一组全局JavaScript函数,用来进行一些常用的操作,例如: 比较两个对象迭代对象进行数据格式转换 全局API函数可以通过an…

Java 9幕后花絮:新功能从何而来?

找出Java幕后发生的事情,以及新功能如何实现 在上一篇文章中,我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能,并简要提到了将新功能添加到下一个版本之前要经历的过程。 由于此过程几乎影响了所有Java开发人员,但大多数…

TypeScript 联合类型(union type)

TS是JS的超集,在JS的基础上添加了一套类型系统,这样的TS可以被静态分析带来的好处显而易见。 let val: string val;声明一个string类型的变量val。 let val: string val; val 1; // Type number is not assignable to type string.因为number类型和…

sudo apt-get install libstdc++6

sudo apt-get install libstdc6 yum install libncurses.so.5 sudo apt-get install libncurses.so.5 sudo apt-get install lib32ncurses5 apt-get update把源更新一下 使用gdb时的指令 (gbd) info line *0x08xxxx sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.…

AngularJS快速入门指南03:表达式

AngularJS通过表达式将数据绑定到HTML。 AngularJS表达式 AngularJS表达式写在双大括号中:{{ 表达式语句 }}。 AngularJS表达式绑定数据到HTML的方式与ng-bind指令的方式相同。 AngularJS会准确地将表达式“输出”为计算的结果。 AngularJS表达式与JavaScript表达式…

零基础快速上手HarmonyOS ArkTS开发2---ArkTS开发实践

ArkTS开发实践: 接着上一次零基础快速上手HarmonyOS ArkTS开发1---运行Hello World、ArkTS开发语言介绍继续, 在上一次对于ArkTS的基础知识进行了学习,依照官方的课程计划,还有两个具体的小案例需要来实践实践: 实践出…

无状态Spring安全性第2部分:无状态身份验证

Spring Stateless Security系列的第二部分是关于以无状态方式探索身份验证的方法。 如果您错过了CSRF的第一部分,可以在这里找到。 因此,在谈论身份验证时,其全部内容就是让客户端以可验证的方式向服务器标识自己。 通常,这始于服…

TypeScript 交叉类型(intersection type)

在TS中和联合类型(union type)对应的还有交叉类型(intersection type)。 交叉类型的出现主要为了组合多个对象类型(object type),因为相对于interface,object type没法继承,那么就可以通过union type来实现混合的目的,从而实现继承…

【转】JAVA中的转义字符

JAVA中转义字符: 1.八进制转义序列:\ 1到3位5数字;范围\000~\377 \0:空字符 2.Unicode转义字符:\u 四个十六进制数字;0~65535 \u0000:空字符 3.特殊字符:就3个 \"&#xff1a…

八、VueJs 填坑日记之参数传递及内容页面的开发

我们在上一篇博文中&#xff0c;渲染出来了一个列表&#xff0c;并在列表中使用了router-link标签&#xff0c;标签内的&#xff1a;to就是链接地址&#xff0c;昨天咱们是<router-link :to"/content/ i.id">这样写的&#xff0c;今天我们来完成内容页面的渲染…