小记3 - 1解构赋值:更高效的提取变量 - 解构数组

背景:解构(destructuring)有何用?

let heros   =   {                               
          no1:  "吕布",                               
          no2:  "张飞",
          weapons:  [ "刀","剑","弓箭"]     
};
//  从对象中提取数据
 let lb = heros.no1,  zs = heros.no2, weapons = heros.weapons;

想象一下,若heros中有100万个变量需要提取处理呢?若 是多层嵌套的数据结构呢?可能会为了一点数据而挖掘整个结构,做大量低效重复的工作。

解构赋值

解构赋值--使得把数据结构分解为更小的部分时,提取数据会变得更容易,更高效。
解构赋值语法是一种 Javascript 表达式。解构使用的语法--就是对象与数组的字面量语法。--按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

基本原则如下:

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

数组的解构赋值

1 变量声明并赋值时的解构 或者先声明变量再赋值
let  foo = ["one", "two", "three"];
let  [m, n, three] = foo;
console.log(m); // "one"
console.log(n); // "two"
console.log(three); // "three"
//-或者
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo); // 1
console.log(bar); // 2
console.log(baz); // 3


//先声明再赋值
let a, b;
[a, b] = [1, 2];

注意1:在使用 var 、 let 、 const 进行数组解构时,必须提供初始化 器(即等号 右边的值)

const [a ,b];
let [d,e];
// Uncaught SyntaxError: Missing initializer in destructuring declaration

注意2:如果解构不成功,变量的值就等于undefined。

let [foo] = [];
let [bar, foo] = [1];
//以上两种情况都属于解构不成功,foo的值都会等于undefined。

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

let [x, y] = [1, 2, 3];//     x//1    y //2
let [a, [b], d] = [1, [2, 3], 4];//     a //1   b // 2  d // 4

注意4:解构报错--如果等号的右边不是数组(或者严格地说,不是可遍历的结构,不具备 Iterator 接口),那么将会报错。

// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
2 忽略某些值,只对感兴趣值解构
let [ , , third] = ["foo", "bar", "baz"];  //逗号-, 为数组前面的项提供的占位符
console.log(third);  // "baz"
3 默认值

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

const [a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7  --默认值生效

let [x = 1] = [undefined];
x // 1   --默认值生效
let [x = 1] = [null];
x // null

注意1:如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

function f() {
    console.log('aaa');
}
let [x = f()] = [1];  //因为x能取到值,所以函数f根本不会执行。

//上面的代码其实等价于下面的代码。
let x;
if ([1][0] === undefined) {
  x = f();
} else {
  x = [1][0];
}

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

let [x = 1, y = x] = [2];    // x=2; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined 
//--因为x用y做默认值时,y还没有声明
4 剩余项 (...) -- 将剩余数组赋值给一个变量(数组)

当解构一个数组时,可以使用剩余模式,将数组剩余部分赋值给一个变量。

var [a, ...b] = [1, 2, 3];
console.log(a); // 1
console.log(b); // [2, 3]   --注意,这是个数组

注意:如果剩余元素右侧有逗号,会抛出 SyntaxError因为剩余元素必须是数组的最后一个元素,之后不能再有逗号,否则就是语法错误。

var [a, ...b,] = [1, 2, 3];
// SyntaxError: rest element may not have a trailing comma

应用1::若要取出特定项 并要求保留剩余的值,则剩余项是非常有用的。
应用2:方便地克隆数组在JS中是个明显被遗漏的功能。
在ES5中常用的concat()方法来克隆数组 (方便简单);在ES6中,使用剩余项的语法克隆数组(小技巧)

//  在   ES5 中克隆数组 
let colors  =   [   "red",  "green",    "blue"  ]; 
let clonedColors    =   colors.concat();
colors[2]   = "skyblue";
console.log(clonedColors);      //"[red,green,blue]"

concat()方法本意是合并两个数组,但不使用任何参数来调用此方法,会获得原 数组的一个克隆品。

//  在ES6中,使用剩余项的语法克隆数组 ,达到上述同样效果
let colors  =   [   "red",  "green",    "blue"  ]; 
let [   ...clonedColors ]   =   colors;
colors[2]   = "skyblue";
console.log(clonedColors);      //"[red,green,blue]"
5 嵌套的数组 解构

在整个解构模式中插入另一 个数组模式,解构操作会下行到 嵌套的数组中。可以使用任意深 度的数组嵌套解构。

let colors = [  "red",[ "green", "lightgreen" ],    "blue"  ];
let [   firstColor, [   secondColor ]   ]   =   colors;
console.log(firstColor);    //  "red" 
console.log(secondColor);  //   "green" 

应用篇

交换变量 - 在一个解构表达式中可以轻松交换两个变量的值。
//在 ES5 中互换值需要使用第三个变量作为临时变量:
 let    a = 1, b = 2, tmp;
 tmp    =a ;  a = b;  b = tmp;
console.log(a); //  2 
console.log(b); //  1
//  在   ES6 中互换值 
let a = 1, b    =   2;
[   a,  b   ]   =   [   b,  a   ];
console.log(a); //  2 
console.log(b);       //1
解析一个从函数返回的数组

从一个函数返回一个数组是十分常见的情况。解构使得处理返回值为数组时更加方便。

function f() {
  return [1, 2];
}
let a, b; 
[a, b] = f(); 
console.log(a); // 1
console.log(b); // 2

总结

本质上,解构赋值这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
数组的元素是按次序排列的,变量的取值由它的位置决定;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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