博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6 - 变量的解构赋值解析
阅读量:6832 次
发布时间:2019-06-26

本文共 5097 字,大约阅读时间需要 16 分钟。

  • ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
  • 如果解构不成功,变量的值就等于undefined。

数组的解构赋值

例子:

let [temA, temB, temC] = ['AAAA', 'BBBB', 'CCCC']console.log(temA); // AAAAconsole.log(temB); // BBBBconsole.log(temC); // CCCC复制代码

上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。本质上这种写法属于‘模式匹配‘,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面看些复杂的例子:

let [temA, [temB, temC], temD] = ['AAAA', ['BBBB', 'CCCC'], 'DDDD'];console.log(temA); // AAAAconsole.log(temB); // BBBBconsole.log(temC); // CCCCconsole.log(temD); // DDDDlet [ , , temA] = ['AAAA', 'BBBB', 'CCCC'];console.log(temA); // CCCClet [temA, temB, temC] = ['AAAA'];console.log(temC); // undefined复制代码

解构一般有三种情况,1.完全解构;2.不完全解构;3.解构不成功。

在上述例子中存在完全解构和解构不成功的例子,下面来看一下不完全解构的例子

let [temA, temB] = ['AAAA', 'BBBB', 'CCCC'];console.log(temA); // AAAAconsole.log(temB); // BBBBlet [temA, [temB], temD] = ['AAAA', ['BBBB','CCCC'], 'DDDD'];console.log(temA); // AAAAconsole.log(temB); // BBBBconsole.log(temD); // DDDD复制代码

不完全解构:即等号左边的模式,只匹配一部分的等号右边的数组,这种情况下解构依然成功。

如果等号的右边不是数组,或者说不是可遍历的结构,那么将会报错,看下面的例子

let [temA] = 1;let [temB] = false;let [temC] = NaN;let [temD] = undefined;let [temE] = null;let [temF] = {};复制代码

上面的语句都会报错:Uncaught TypeError: undefined is not a function

  • 解构赋值允许指定默认值
let [temA, temB = 'bbbb'] = ['AAAA'];console.log(temB); // bbbblet [temA, temB = 'bbbb'] = ['AAAA', undefined];console.log(temB); // bbbb        let [temA, temB = 'bbbb'] = ['AAAA', null];console.log(temB); // null复制代码

数组成员为undefined时,默认值仍会生效;如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined。

对象的解构赋值

对象的解构与数组有一个重要的不同,数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

let {temA, temB} = {temA: 'AAAA', temB: 'BBBB'};console.log(temA); // AAAAconsole.log(temB); // BBBB// 上面例子与下面例子等同let {temA: temA, temB: temB} = {temA: 'AAAA', temB: 'BBBB'};console.log(temA); // AAAAconsole.log(temB); // BBBB复制代码

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

如果变量名和属性名不一致,必须写成下面例子这样

let {temA: temG} = {temA: 'AAAA', temB: 'BBBB'}console.log(temG); // AAAAlet obj = {temA: 'AAAA', temB: 'BBBB'};let {temA: A, temB: B} = obj;console.log(A); // AAAAconsole.log(B); // BBBB复制代码

与数组一样,解构也可以用于嵌套解构的对象,看下面例子

let obj = {    data: [        'temA',        {temB: 'BBBB'}    ]};let {data: [temA, {temB}]} = obj;console.log(temA); // temAconsole.log(temB); // BBBB复制代码
const node = {    res: {        parent: {            num: 1,            content: 'Content'        }    }}let {res, res: {parent}, res: {parent: {num}}} = node;console.log(res); // Object {parent: Object}console.log(parent); // Object {num: 1, content: "Content"}console.log(num); // 1复制代码

上面代码有三次解构赋值,分别是对res、parent、num三个属性的解构赋值。

注意,最后一次对num属性的解构赋值之中,只有num是变量,res和parent都是模式,不是变量。

如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。

let {node: {temA}} = {temB: 'temC'};// Uncaught TypeError: Cannot match against 'undefined' or 'null'.复制代码
  • 对象的解构也能制定默认值
var {temA = 'AAAA'} = {};console.log(temA); // AAAA        var {temA, temB = 'BBBB'} = {temA: 'AAAA'};console.log(temA); // AAAAconsole.log(temB); // BBBB        var {temA: temB = 'BBBB'} = {};console.log(temB); // BBBB        var {temA: temB = 'BBBB'} = {temA: 'AAAA'};console.log(temB); // AAAA复制代码

字符串的解构赋值

字符串也可以解构赋值,在解构赋值时会被转换成类似的数组对象。其中还有一个length属性,因此还可以对这个属性解构赋值。

const [temA, temB, temC, temD, temE] = 'world';console.log(temA); // wconsole.log(temB); // oconsole.log(temC); // rconsole.log(temD); // lconsole.log(temE); // d        let {length: len} = 'world';console.log(len); // 5复制代码

数值的解构赋值

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

let {temA: temB} = 123;console.log(temB === Number.prototype.temA);复制代码

布尔值的解构赋值

布尔值在解构赋值时会和数值一样,先转为对象。

let {temA: temB} = true;console.log(temB === Number.prototype.temA);复制代码

函数参数的解构赋值

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

function add([argA, argB]){    return argA + argB;}console.log(add([1, 2])); // 3复制代码

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

function add([argA, argB = 5]){    return argA + argB;}console.log(add([1])); // 6function add({argA, argB = 5} = {}){    return argA + argB;}console.log(add({argA: 1})); // 6复制代码

变量解构赋值的用途

  1. 交换变量的值
let temA = 'AAAA';let temB = 'BBBB';[temA, temB] = [temB, temA];console.log(temA); // BBBBconsole.log(temB); // AAAA复制代码
  1. 从函数返回多个值
function Fn(){    return [1, 2, 3];}let [temA, temB, temC] = Fn();// 返回一个数组        function Fn(){    return {        temA: 'AAAA',        temB: 'BBBB'    }}let {temA, temB} = Fn();// 返回一个对象复制代码
  1. 函数参数的定义
function Fn([temA, temB, temC]){    console.log(temA + temB + temC);}Fn([1, 2, 3]);复制代码
  1. 提取JSON数据
let jsonData = {    id: 1,    name: 'Xiao Duan',    data: [22, 99]}let {id, name, data: number} = jsonData;console.log(id, name, number); // 1 "Xiao Duan" [22, 99]        复制代码
  1. 函数参数的默认值
jQuery.ajax = function (url, {    async = true,    beforeSend = function () {},    cache = true,    complete = function () {},    crossDomain = false,    global = true,    // ... more config} = {}) {    // ... do stuff};复制代码
  1. 遍历Map结构
const map = new Map();map.set('temA', 'hello');map.set('temB', 'world');for (let [key, value] of map){    console.log(key + " is " + value);}复制代码
  1. 输入模块的制定方法 加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");复制代码

转载于:https://juejin.im/post/5ca08170e51d45301b5c90f7

你可能感兴趣的文章
Swift - 使用UISearchController实现带搜索栏的表格
查看>>
web接口测试之GET与POST请求
查看>>
关于LR中的EXTRARES
查看>>
转:如何转换Android打包用jks格式keystore证书为Air用pkcs12格式p12证书
查看>>
光伏发电系列:关于光伏发电站的建设成本和资金回收周期
查看>>
Linux内核源代码目录树结构
查看>>
js常用正则表达式
查看>>
jQuery-1.9.1源码分析系列(七) 钩子(hooks)机制及浏览器兼容续
查看>>
P - A + B(第二季水)
查看>>
Atitit. 真正的全中国文字attilax易语言的特点以及范例
查看>>
iOS开发--AVFoundation自定义相机
查看>>
阅读GIC-500 Technical Reference Manual笔记
查看>>
JavaWeb学习总结(二) Servlet
查看>>
各类注解笔记:
查看>>
【Python】存储数据
查看>>
WARN: Establishing SSL connection without server's identity verification is not recommended
查看>>
高性能分布式执行框架——Ray
查看>>
Art: Neural Style Transfer
查看>>
jsp注释<%-- -- %> 和 <!-- --> 的区别
查看>>
关于Linux操作系统层次结构分析
查看>>