C#里没有这种变态的方法。

虽然变态,但看起来不错的样子。

变量的解构赋值

  • 完全解构:本质上,这种写法属于“模式匹配”,;
  • 不完全解构:同时支持“不完全解构”
let [x, y] = [1, 2, 3];
x //
y // let [a, [b], d] = [1, [2, 3], 4];
a //
b //
d //
  • 数组:左边是数组,能遍历,但右边的不能,将报错。
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
  • 集合:事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
  • 函数:fibs是一个 Generator 函数,原生具有 Iterator 接口。解构赋值会依次从这个接口获取值。
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
} let [first, second, third, fourth, fifth, sixth] = fibs();
sixth //
  • 默认值:当一个数组成员严格等于undefined,默认值才会生效
let [x = 1] = [undefined];
x // let [x = 1] = [null];  // null不严格等于undefined
x // null

若取到值,则不会触发默认值。

对象的解构赋值

对象的属性没有次序,变量必须与属性同名,才能取到正确的值。【字典匹配模式,不是通过位置】

简单匹配

  • key的匹配:
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb" let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
  • value的配置:
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa" let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

嵌套匹配

冒号代表的“模式”:如下,这时p是模式,不是变量,因此不会被赋值。如果p也要作为变量赋值,可以写成下面这样【见2】。

let obj = {
p: [
'Hello',
{ y: 'World' }
]
}; let { p: [x, { y }] } = obj;
let { p, p: [x, { y }] } = obj; <----【2】
x // "Hello" 
y // "World"

强化理解:”模式“就是路径的效果。

const node = {
loc: {
start: {
line: 1,
column: 5
}
}
}; let { loc, loc: { start }, loc: { start: { line }} } = node;
loc // Object {start: Object}
start // Object {line: 1, column: 5}
line // 

模式的计算:不是圆括号,是方括号。

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

危险区:路径若是”越界“了,报错。

// 报错
let {foo: {bar}} = {baz: 'baz'}; // foo这时等于undefined,再取子属性就会报错 let _tmp = {baz: 'baz'};
_tmp.foo.bar // 报错,这就好理解了,没有路径,越界了

危险区:只有不将大括号写在行首,避免 JavaScript 将其解释为代码块。

let x;
({x} = {x: 1});  // 可见圆括号的牛逼之处,such as ({} = 'abc'); 一个毫无意义的写法,但语法没问题!

  扩展 - 可以理解为对象

  • 字符串的解构赋值
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o" let {length : len} = 'hello';
len //
  • 数值和布尔值的解构赋值
let {toString: s} = 123;
s === Number.prototype.toString // true let {toString: s} = true;
s === Boolean.prototype.toString // true
  • undefined和null解构赋值
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

函数参数的解构赋值

支持多套参数:参数放在数组里。

[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]

默认值:

unction move({x = 0, y = 0} = {}) {
return [x, y];
} move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
} move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]
    • 参数默认值可以与解构赋值的默认值,结合起来使用。
function fetch(url, { body = '', method = 'GET', headers = {} } = {}) {
console.log(method);
} fetch('http://example.com', {})
// "GET" fetch('http://example.com')  // 有了双重默认值就不会报错了
// 报错 

练习:

// 写法一
function m1({x = 0, y = 0} = {}) {      #设置了对象解构赋值的默认值
return [x, y];
} // 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}

几个实验:

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

啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

[JS] ECMAScript 6 - Destructuring的更多相关文章

  1. [Node.js] ECMAScript 6中的生成器及koa小析

    原文地址:http://www.moye.me/2014/11/10/ecmascript-6-generator/ 引子 老听人说 koa大法好,这两天我也赶了把时髦:用 n 安上了node 0.1 ...

  2. [JS] ECMAScript 6 - Variable : compare with c#

    前言 范围包括:ECMAScript 新功能以及对象. 当前的主要目的就是,JS的学习 --> ECMAScript 6 入门 let 命令 js 因为let, i的范围限制在了循环中. var ...

  3. [JS] ECMAScript 6 - Class : compare with c#

    Ref: Class 的基本语法 Ref: Class 的基本继承 许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为.目前,有一个提案将这项功能,引入了 ECMAScript. ...

  4. [JS] ECMAScript 6 - Inheritance : compare with c#

    这一章,估计是js最操蛋的一部分内容. 现代方法: 简介 Object.getPrototypeOf() super 关键字 类的 prototype 属性和__proto__属性 原生构造函数的继承 ...

  5. [JS] ECMAScript 6 - String, Number, Function : compare with c#

    字符串的扩展 正则的扩展 数值的扩展 函数的扩展 字符串的扩展 js 字符的 Unicode 表示法 codePointAt() String.fromCodePoint() 字符串的遍历器接口 at ...

  6. [JS] ECMAScript 6 - Prototype : compare with c#

    开胃菜 prototype 对象 JavaScript 语言的继承则是通过“原型对象”(prototype). function Cat(name, color) { // <----构造函数 ...

  7. [JS] ECMAScript 6 - Async : compare with c#

    一段引言: Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对 ...

  8. js (ECMAScript) 对数据处理的 方法、属性总结

    注意:原生类型的数据本身是没有属性.方法的.但是 有的原始类型(如 string),当他 调用属性或方法时,JS引擎会先对原始类型数据进行包装(即隐式的转换为相应的对象)  https://www.c ...

  9. JS ECMAScript 5中的every 和 some方法进行逻辑判断

    ECMA Script 5 中新增两个不错的关于数组元素的逻辑运算方法some, every Array.some(function(item){}); Array.every(function(it ...

随机推荐

  1. APP支付宝支付接入

    1.app支付简介 买家可以在手机,掌上电脑等无线设备的应用程序内,通过支付宝(支付宝app或网页版支付宝)付款购买商品,且资金实行实时到账. 2.申请条件 1.申请前必须拥有经过实名认证的支付宝账户 ...

  2. ORB-SLAM2(一)----使用Eclipse进行开发

    1.导入项目 准备工作 1, first we should make sure the compile with build.sh under ORB_SLAM2-master is OK. 2, ...

  3. spring cloud——feign为GET请求时的对象参数传递

    一.问题重现 楼主在使用feign进行声明式服务调用的时候发现,当GET请求为多参数时,为方便改用DTO对象进行参数传递.但是,在接口调用时feign会抛出一个405的请求方式错误: {"t ...

  4. 使用Date和SimpleDateFormat类表示时间

    Date类: 使用 Date 类的默认无参构造方法创建出的对象就代表当前时间,我们可以直接输出 Date 对象显示当前的时间,显示的结果如下: Date d = new Date(); System. ...

  5. su 与 su - 比较

    原文地址:http://blog.chinaunix.net/uid-25557346-id-2889329.html   今天有一同事说在切换用户的时候,找不到该用户下用户命令,后来仔细检查了一下过 ...

  6. iphone程序适配ipad可以用下面的宏进行尺寸改写

    //判断是否为iPad #define ISIPAD [[[UIDevice currentDevice].model substringToIndex:4] isEqualToString:@&qu ...

  7. 版本视图找不到数据 EDITIONING VIEW

    Oracle database 12 以后的版本,特别在EBS R12.2.X加入了版本视图这种技术,跟MOAC有点像. CREATE OR REPLACE FORCE EDITIONING VIEW ...

  8. WordPress主题开发:通过page的ID或者别名获取内容

    访问地址:xx/?page_id=12 如果是在当前页面,只需要通过循环就可以输出对应的信息 <?php if(have_posts()):while(have_posts()):the_pos ...

  9. 【OpenCV】OpenCV中GPU模块使用 (转)

    CUDA基本使用方法 在介绍OpenCV中GPU模块使用之前,先回顾下CUDA的一般使用方法,其基本步骤如下: 1.主机代码执行:2.传输数据到GPU:3.确定grid,block大小: 4.调用内核 ...

  10. Std::map too few template arguments

    在上述的代码中,红色波浪线的部分编译的时候报错: error C2976: 'std::map' : too few template arguments 换成std::map<std::str ...