2、变量的解构赋值

1、数组的解构赋值

基本用法

本质上,只要等号两边的模式相同,左边的变量就会被赋予对应的值,...表示将剩下的值赋予此变量,无剩余则赋值为空数组,解构不成功则赋值为undefined。等号两边都要为数组。

let a = 1;
let b = 2;
let c = 3;
//ES6可以写成
let [a, b, c] = [1, 2, 3];

//多重数组的例子
let [a, [[b], c]] = [1, [[2], 3]];
a // 1
b // 2
c // 3

//对应位置赋予对应的值
let [ , , c] = ["1", "2", "3"];
c // "3"
let [a, , c] = [1, 2, 3];
a // 1
c // 3

//...语法有剩余值时
let [a, ...z] = [1, 2, 3, 4];
a // 1
z // [2, 3, 4]

//...语法无剩余值时
let [a, b, ...z] = ['a'];
a // "a"
b // undefined
z // [] 空数组

默认值

解构赋值可以使用默认值,当且仅当变量的值全等于(===)undefined时,才会使用默认值,即使是等于null时也不会使用默认值。

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

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

let [x = 1] = [null]; x // null

当默认值是一个表达式的时候(例如一个行数表达式),若变量能够取到值(值不全等于undefined),则表达式不会执行。

function f() {
  console.log('a');
}
let [x = f()] = [1]; //f()不会执行,y=1

默认值可以引用解构赋值中的其他变量,前提是变量已经声明

let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // y在x引用的时候还没有声明,所以报错。

2、对象的解构赋值

与数组的解构赋值不同的是,数组解构是按照元素的次序赋值的,而对象则不受次序的影响,变量必须与属性同名,才能被赋值,没有同名属性则赋值为undefined。

let { pro1, pro2 } = { pro1: "1", pro2: "2" };
pro1 // "1"
pro2 // "2"
//上述表述是一种缩写,其本质是
let { pro1:pro1, pro2:pro2 } = { pro1: "1", pro2: "2" };

//在等号左边时,:号左边的pro1和pro2是定义匹配模式,真正被赋值的是:号右边的pro1和pro2,当匹配模式和属性名同名时,可以使用缩写
let { proa:prox, prob:proy } = { proa: "1", prob: "2" };
prox //"1"
proy //"2"

对象解构中左边的变量一定是由:组成的一对匹配模式和属性名。只有一个匹配模式时,一定是匹配模式和属性名相同,使用了简写。

var obj= {
  a: {
    b: {
      c: 1,
      d: 2
    }
  }
};
var { a: { b: { c }} } = obj;
a // 报错,a在:左边,是匹配模式,不是属性名
b // 报错,b在:左边,是匹配模式,不是属性名
c // 1

对象的解构赋值同样支持默认值,规则与数组的解构相似:

  1. 当且仅当变量值全等于(===)undefined时,才会取默认值。
  2. 如果解构失败,变量的值等于undefined。

当大括号位于本行的首位时,需要加上小括号,因为 { } 表示一个代码块,不是一个单独的语句。

let x;
{x} = {x: 1}; // 语法错误,左边是一个代码块,不是一个声明。

({x} = {x: 1}); // 加上小括号,成为一个单独的语句,语法正确。

当变量名与现有对象的属性名相同时,可以直接使用对象赋值。

let { log, sin, cos } = Math;
log // Math.log
sin // Math.sin
cos // Math.cos

因为在JavaScript中,数组是特殊的对象,所以可以用数组进行对象属性的结构。

let arr = [1, 2, 3];
let {0 : a, [arr.length - 1] : b} = arr;
a // 1
b // 3

3、字符串的解构赋值

字符串进行结构赋值时,被转化为了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';
a // 'h'
let {length : len} = 'hello';
len // 5   因为右边'hello'字符串被转化为了一个类似数组的对象,具有length属性,所以可以直接赋值给左边同名的匹配模式。

4、数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

解构赋值的规则是,只要右边不是对象或者数组,就将其转化为对象,再进行匹配赋值。
因为undefined和null不能转化为对象,所以单独将这两个值当做右边的值进行匹配赋值时会报错。

let { prop: x } = undefined; // 报错
let { prop: y } = null; // 报错

5、函数参数的解构赋值

function add([x, y]){
  return x + y;
}
add([1,2]); // 传输数组参数相当于执行了 [x,y]=[1,2];x和y被分别赋值为1和2

函数参数的解构也可以使用默认值,但下面两种情况不同:

function move({x = 0, y = 0} = {}) {
  return [x, y];
} 

这种方式表示x和y没有给定值时默认值为0,x和y是分开赋值的,只要参数中存在没有传入的项,就使用其默认值。
即只要某一项参数不存在,就一定会使用其默认值。

function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
} 

这种方式指定的是整个参数的默认值,而不是单独指定x和y,x和y是当做一个整体。只有当完全不传任何参数时,才会使用默认值(传入空对象也不会使用默认值),无论是单独传了x参数,还是单独传了y参数,未传的项都不会使用默认值。
即只要存在参数,且参数不全等于(===)undefined,就一定不会使用默认值。


6、圆括号问题

ES6的规则是:只要有可能导致解构歧义,就不得使用圆括号。
所以,在非必要情况下,没有必要添加圆括号(事实上大部分圆括号都是没有必要添加的)。

不允许使用圆括号的情况
  1. 声明语句中不允许使用圆括号
  2. 函数参数中,匹配模式不允许使用圆括号,因为函数参数也属于变量声明
  3. 不能将整个模式或嵌套中的某一整层放在圆括号当中。

7、解构用途

交换变量的值
let x = 1;
let y = 2;

[x, y] = [y, x]; // 简洁易懂的交换

从函数返回多个值

当函数需要返回多个值时,将这些值组成一个数组或对象,返回这个数组或对象,然后再用解构赋值来取的各项的值。

// 返回一个数组

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

函数参数的定义(包括函数参数使用默认值)
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

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

提取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]
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • ES6允许按照一定的模式,从数组和对象中提取值,并对变量进行赋值。这对于解析json数据和函数参数等操作是非常有帮...
    exialym阅读 536评论 0 2
  • 1.数组的解构赋值 2.对象的解构赋值 3.字符串的解构赋值 4.数值和布尔值的解构赋值 5.函数参数的解构赋值 ...
    卞卞村长L阅读 916评论 0 0
  • 本文通过学习阮一峰的博客,外加自己的理解,整理了一下我对js变量的解构赋值的理解。 数组的解构赋值 对象的解构赋值...
    宋乐怡阅读 466评论 0 2
  • 数组的解构赋值 基本用法 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destru...
    呼呼哥阅读 429评论 0 3
  • 刘长战先生是我的小学班主任,从四年级至六年级,舍去其间他被调任初二班主任的半年,我们一起生活了两年半的动人时光。 ...
    猪鼻子插葱阅读 364评论 1 2