这阵子因为要学习React Native ,而RN必备的知识就是JS,所以开始学习起来了Js,在此声明写博客就是为了更好的学习,总结一些我学习过程中知识点,有不同意见的请尽情发表!

1 什么是解构赋值

解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性赋给各种变量。这种赋值语法极度简洁,同时还比传统的属性访问方法更为清晰。

通常来说,你很可能这样访问数组中的前三个元素:

    var first = someArray[0];var second = someArray[1];var third = someArray[2];

如果使用解构赋值的特性,将会使等效的代码变得更加简洁并且可读性更高:

var [first, second, third] = someArray;

SpiderMonkey(Firefox的JavaScript引擎)已经支持解构的大部分功能,但是仍不健全。你可以通过bug 694100跟踪解构和其它ES6特性在SpiderMonkey中的支持情况。

2 数组与迭代器的解构

以上是数组解构赋值的一个简单示例,其语法的一般形式为:

[ variable1, variable2, ..., variableN ] = array;

这将为variable1到variableN的变量赋予数组中相应元素项的值。如果你想在赋值的同时声明变量,可在赋值语句前加入varletconst关键字,例如:

var [ variable1, variable2, ..., variableN ] = array;let [ variable1, variable2, ..., variableN ] = array;const [ variable1, variable2, ..., variableN ] = array;

事实上,用变量来描述并不恰当,因为你可以对任意深度的嵌套数组进行解构:

var [foo, [[bar], baz]] = [1, [[2], 3]];console.log(foo);// 1console.log(bar);// 2console.log(baz);// 3

此外,你可以在对应位留空来跳过被解构数组中的某些元素:

var [,,third] = ["foo", "bar", "baz"];console.log(third);// "baz"

而且你还可以通过“不定参数”模式捕获数组中的所有尾随元素:

var [head, ...tail] = [1, 2, 3, 4];console.log(tail);// [2, 3, 4]

当访问空数组或越界访问数组时,对其解构与对其索引的行为一致,最终得到的结果都是:undefined

    console.log([][0]);// undefinedvar [missing] = [];console.log(missing);// undefined

请注意,数组解构赋值的模式同样适用于任意迭代器:

    function* fibs() {var a = 0;var b = 1;while (true) {yield a;[a, b] = [b, a + b];}}var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(first);//0
console.log(second);//1
console.log(third);//2
console.log(fourth);//3
console.log(fifth);//4
console.log(sixth);//5

着重讲下: var [first, second, third, fourth, fifth, sixth] = fibs();相当于调用了五次next方法,我们看下调用的过程,第一次调用a=0,通过yield返回0 赋值给first,[a,b] = [0,1] 第二次调用, [a,b] = [1,2],a=1通过yield返回1,赋值给second,第三次 [a,b] = [2,3] 依次类推,[first, second, third, fourth, fifth, sixth] = [0,1,2,3,4,5] .(不了解迭代器可以查看:迭代器)。

3 对象的解构

通过解构对象,你可以把它的每个属性与不同的变量绑定,首先指定被绑定的属性,然后紧跟一个要解构的变量。

    var robotA = { name: "Bender" };var robotB = { name: "Flexo" };var { name: nameA } = robotA;var { name: nameB } = robotB;console.log(nameA);// "Bender"console.log(nameB);// "Flexo"

当属性名与变量名一致时,可以通过一种实用的句法简写:

var { foo, bar } = { foo: "lorem", bar: "ipsum" };console.log(foo);// "lorem"console.log(bar);// "ipsum"

上面的代码给解构对象赋值了一个具有具体属性的对象(这里简称属性对象),必需保证解构对象中的变量名和属性对象中的属性名相同,如果我们把属性对象中的名字改变的话,如下:

var { foo, bar } = { foo2: "lorem", bar2: "ipsum" };//undefinedconsole.log(foo);//undefinedconsole.log(bar);

上面的代码,返回值是undefined。

那么改变其中的一个属性名呢,又是什么样的效果,如下:

var { foo, bar } = { foo: "lorem", bar2: "ipsum" };//loremconsole.log(foo);//undefinedconsole.log(bar);

上面的代码可以看出解构变量foo被赋值了,bar没有被赋值。如果我们直接给解构赋予默认值呢,来看下代码:

var { foo = "Hello", bar = "World !" } = { foo: "lorem", bar2: "ipsum" };//loremconsole.log(foo);//World !console.log(bar);

上面的代码,变量foo在属性对象中找到了自己想要的值,就不在使用默认值了,而bar没有找到自己想要的值,就使用了默认值。

与数组解构一样,你可以随意嵌套并进一步组合对象解构:

    var complicatedObj = {arrayProp: ["Zapp",{ second: "Brannigan" }]};var { arrayProp: [first, { second }] } = complicatedObj;console.log(first);// "Zapp"console.log(second);// "Brannigan"

当你解构一个未定义的属性时,得到的值为undefined

    var { missing } = {};console.log(missing);// undefined

请注意,当你解构对象并赋值给变量时,如果你已经声明或不打算声明这些变量(亦即赋值语句前没有letconstvar关键字),你应该注意这样一个潜在的语法错误:

    { blowUp } = { blowUp: 10 };// Syntax error 语法错误

为什么会出错?这是因为JavaScript语法通知解析引擎将任何以{开始的语句解析为一个块语句(例如,{console}是一个合法块语句)。解决方案是将整个表达式用一对小括号包裹:

    ({ safe } = {});// No errors 没有语法错误

4 解构值不是对象、数组或迭代器

当你尝试解构nullundefined时,你会得到一个类型错误:

    var {blowUp} = null;// TypeError: null has no properties(null没有属性)

然而,你可以解构其它原始类型,例如:布尔值数值字符串,但是你将得到undefined

    var {wtf} = NaN;console.log(wtf);// undefined

你可能对此感到意外,但经过进一步审查你就会发现,原因其实非常简单。当使用对象赋值模式时,被解构的值需要被强制转换为对象。大多数类型都可以被转换为对象,但nullundefined却无法进行转换。当使用数组赋值模式时,被解构的值一定要包含一个迭代器。

5 默认值

当你要解构的属性未定义时你可以提供一个默认值:

    var [missing = true] = [];console.log(missing);// truevar { message: msg = "Something went wrong" } = {};console.log(msg);// "Something went wrong"var { x = 3 } = {};console.log(x);// 3

(译者按:Firefox目前只实现了这个特性的前两种情况,第三种尚未实现。详情查看bug 932080。)

6 解构的实际应用

(1)函数参数定义

作 为开发者,我们需要实现设计良好的API,通常的做法是为函数为函数设计一个对象作为参数,然后将不同的实际参数作为对象属性,以避免让API使用者记住 多个参数的使用顺序。我们可以使用解构特性来避免这种问题,当我们想要引用它的其中一个属性时,大可不必反复使用这种单一参数对象。

function removeBreakpoint({ url, line, column }) {// ...}

这是一段来自Firefox开发工具JavaScript调试器(同样使用JavaScript实现——没错,就是这样!)的代码片段,它看起来非常简洁,我们会发现这种代码模式特别讨喜。下面我们看这两个方法的有什么不同之处:

// 写法一
function m1({x = 0, y = 0} = {}) {return [x, y];
}
// 写法二
function m2({x, y} = { x: 0, y: 0 }) {return [x, y];
}

首先要知道这两个方法的参数都是解构对象,方法一给参数赋予默认值({}即空对象),并且给解构对象设置了默认值,变量x默认值为0,变量y默认值为0;方法二也给参数赋予了默认值(属性对象{ x: 0, y: 0 }),但是没有给解构对象赋值,下面我们看下效果:

// 函数没有参数的情况
console.log(m1());  // [0, 0]
console.log(m2()); // [0, 0]
// x和y都有值的情况
console.log(m1({x: 3, y: 8})); // [3, 8]
console.log(m2({x: 3, y: 8})); // [3, 8]
// x有值,y无值的情况
console.log(m1({x: 3})); // [3, 0]
console.log(m2({x: 3}));// [3, undefined]
// x和y都无值的情况
console.log(m1({}));// [0, 0];
console.log(m2({})); // [undefined, undefined]
console.log(m1({z: 3}));// [0, 0]
console.log(m2({z: 3}));// [undefined, undefined]

在没有传递参数的情况,方法一首先在{}对象中找自己想要的值,没有找到,就是用了解构对象中的默认值,方法二在{ x: 0, y: 0 }对象中找到了自己想要的值,直接拿来使用了;在有参数传递过来的情况下,无论方法一还是方法二,参数(解构对象)的指针都会指向传递过来的参数(属性对象),不再指示{}或{ x: 0, y: 0 }也就是说在找默认值就不能在这两个对象中找了,和他们已经没有半毛钱关系了,如果传递过来参数包含x、y那么直接使用,如果缺少x或y那么会到解构对象中寻找默认值,对于方法二,没有设置解构对象默认值,那么对不起只能返回undefined。函数更多的扩展点击查看:函数的扩展。

(2)配置对象参数

延伸一下之前的示例,我们同样可以给需要解构的对象属性赋予默认值。当我们构造一个提供配置的对象,并且需要这个对象的属性携带默认值时,解构特性就派上用场了。举个例子,jQuery的ajax函数使用一个配置对象作为它的第二参数,我们可以这样重写函数定义:

    jQuery.ajax = function (url, {async = true,beforeSend = noop,cache = true,complete = noop,crossDomain = false,global = true,// ... 更多配置}) {// ... do stuff};

如此一来,我们可以避免对配置对象的每个属性都重复var foo = config.foo || theDefaultFoo;这样的操作。

(编者按:不幸的是,对象的默认值简写语法仍未在Firefox中实现,我知道,上一个编者按后的几个段落讲解的就是这个特性。点击bug 932080查看最新详情。)

(3)与ES6迭代器协议协同使用

ECMAScript 6中定义了一个迭代器协议,我们在《深入浅出ES6(二):迭代器和for-of循环》中已经详细解析过。当你迭代Maps(ES6标准库中新加入的一种对象)后,你可以得到一系列形如[key, value]的键值对,我们可将这些键值对解构,更轻松地访问键和值:

    var map = new Map();map.set(window, "the global");map.set(document, "the document");for (var [key, value] of map) {console.log(key + " is " + value);}// "[object Window] is the global"// "[object HTMLDocument] is the document"

只遍历键:

    for (var [key] of map) {// ...}

或只遍历值:

    for (var [,value] of map) {// ...}

(4)多重返回值

JavaScript语言中尚未整合多重返回值的特性,但是无须多此一举,因为你自己就可以返回一个数组并将结果解构:

    function returnMultipleValues() {return [1, 2];}var [foo, bar] = returnMultipleValues();

或者,你可以用一个对象作为容器并为返回值命名:

    function returnMultipleValues() {return {foo: 1,bar: 2};}var { foo, bar } = returnMultipleValues();

这两个模式都比额外保存一个临时变量要好得多。

    function returnMultipleValues() {return {foo: 1,bar: 2};}var temp = returnMultipleValues();var foo = temp.foo;var bar = temp.bar;

或者使用CPS变换:

    function returnMultipleValues(k) {k(1, 2);}returnMultipleValues((foo, bar) => ...);

(5)使用解构导入部分CommonJS模块

你是否尚未使用ES6模块?还用着CommonJS的模块呢吧!没问题,当我们导入CommonJS模块X时,很可能在模块X中导出了许多你根本没打算用的函数。通过解构,你可以显式定义模块的一部分来拆分使用,同时还不会污染你的命名空间:

const { SourceMapConsumer, SourceNode } = require("source-map");

参考: Destructuring由浅入深

JS之解构( Destructuring)相关推荐

  1. js 对象解构_JS对象:解构

    js 对象解构 JS对象:TL; DR (JS Objects: TL;DR) JavaScript has been plagued since the beginning with misunde ...

  2. JS:ES6-3 解构赋值与模板字符串

    什么是解构赋值: ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值: 代码演示及相关说明: <!DOCTYPE html> <html> < ...

  3. js 对象解构 默认值 重命名

    本代码案例中,reduce的model是一个immutable类型,所以要先toJS const { managerName: manager, oManagerName: oManager = {} ...

  4. 【javascript】js解构赋值中使用别名

    let person = {name:"沉默小管",age:18 } //js的解构,把name别名成myName,之后就可以使用myName替换name let {name:my ...

  5. ES6新特性之解构表达式

    解构表达式 什么是解构? -- ES6中允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称为解构 (Destructuring). 数组解构 比如有一个数组: let arr = [1, ...

  6. ES6(一)——字面量的增强、解构、let/const、块级作用域、暂时性死区

    一.字面量的增强 ES6中对 对象字面量 进行了增强,称之为 Enhanced object literals(增强对象字面量). 字面量的增强主要包括下面几部分: 属性的简写:Property Sh ...

  7. TypeScript笔记 5--变量声明(解构和展开)

    解构是什么 解构(destructuring assignment)是一种表达式,将数组或者对象中的数据赋给另一变量. 在开发过程中,我们经常遇到这样问题,需要将对象某个属性的值赋给其它两个变量.代码 ...

  8. JavaScript对象解构

    JS对象解构 1. 什么是对象解构 ? 2. 基础使用 2.1) 变量在解构表达式中声明 变量直接使用属性的名称 变量使用自定义名称 2.2) 变量在解构表达式前声明 3. 嵌套解构 4. 函数参数列 ...

  9. javascript语法_了解JavaScript中的解构,剩余参数和传播语法

    javascript语法 The author selected the COVID-19 Relief Fund to receive a donation as part of the Write ...

最新文章

  1. html 猫链接怎么写,html超链接下划线应该加入吗?
  2. 推荐NHibernate新书:NHibernate 3.0 CookBook[附下载]
  3. unity 200.8m yoy_没错,Unity双十一来了
  4. java guava 使用_Java8-Guava实战示例
  5. 【直播】如何学习计算机视觉各大方向,言有三6大直播集中上线
  6. 用法 stl_【c++】STL里的priority_queue用法总结
  7. 剑指Offer面试题:4.从尾到头打印链表
  8. php如何记录访问请求类型,检测PHP中的请求类型(GET、POST、PUT或DELETE)
  9. Setup SQL Server 2008 Maintenance Plan Email Notifications
  10. C++ 程序运行前内存分区模型
  11. 向量范数证明例题_第八课:向量的范数
  12. UITextfield键盘相关设置
  13. python写扫雷脚本_利用Python实现自动扫雷小脚本
  14. mysql系统调试文字说明_mysql的配置说明
  15. springboot毕设项目超市仓库管理系统15g4i(java+VUE+Mybatis+Maven+Mysql)
  16. 大龄程序员的出路究竟在何处?从369个过来人问答贴里,我们得到了答案
  17. datamodeler mysql_Navicat Data Modeler功能简介
  18. 跑步时戴什么耳机好、最适合跑步用的耳机
  19. linux查看文件打开限制,Linux最大文件打开数使用经验详解
  20. 微软:Visual Studio 2017是迄今为止最高效的版本

热门文章

  1. xmodem,ymodem,zmodem,kermit的主要区别
  2. DB、DBS和DBMS关系
  3. 移动端与PC端设计的几项要点
  4. CAJ转换为PDF+英语文献翻译
  5. c语言求圆锥的表面积和体积_用C语言求圆锥体积
  6. 浙江最新通信施工安全员机考真题及答案解析
  7. 99.扩展183.信息系统运维维护服务
  8. Python简单几行代码实现黑客电影镜头屏幕画面
  9. 特征锦囊:怎么找出数据集中有数据倾斜的特征?
  10. php 九宫格验证码,PHP九宫格抽奖源码示例