解构赋值原理

ES6变量的解构赋值本质上是“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予匹配的右边的值,如果匹配不成功变量的值就等于undefined

ES6中只要某种数据有Iterator接口(也就是可以循环迭代 Iterable对象),都可以进行数组的解构赋值

数组解构

(1)基本赋值

let [a,b,c] = [1,2,3];
console.log(a,b,c);

(2)先声明再赋值

let a,b,c;
[a,b,c] = [1,2,3];
console.log(a,b,c);

(3)不完全解构

let [a,,c,d] = [1,2,3];
console.log(a,c,d); //1 3 undefined

(4)默认参数

如果值为undefined,变量将取得默认参数

let [a=10,b=20,c=30,d=40] = [1,2,3];
console.log(a,b,c,d);//1 2 3 40

(5)剩余参数

let [a=10,...b] = [1,2,3];
console.log(a,b);//1  [2, 3]

(6)Iterable对象(Iterator接口)  会按数组处理

字符串:

let [a,b,c] = "123";
console.log(a,b,c);//1 2 3

Set对象

let set = new Set();
set.add(1).add(2).add(3);
let [a,b,c] = set;
console.log(a,b,c);//1 2 3

Map对象

let map = new Map();
map.set("a",1)
   .set("b",2)
   .set("c",3);

let [[x,m],[y,n],[z]] = map;

console.log(x,y,z,m,n);  //a b c 1 2

Generator函数返回的对象

function* gen() {
  yield "a";
  yield "b";
  yield "c";
}
let genObj = gen();
let [x,y,z] = genObj;
console.log(x,y,z);  a b c

 解构数组可以交换变量

let a = 1, b = 2;
[a, b] = [b, a];
console.log(a,b) //2 1

引发的思考:计算出数组每项的值,解构赋值时一一对应。下面示例中,[b=a, a=3] 数字第一项b=a,该值为1,第二项为3;所以解构赋值a为第一项的值,b为第二项的值

所以,思考下面例子

let a = 1, b = 2;
[a, b] = [b=a, a=3];
console.log(a,b) //1 3

 

对象解构

(1)基本赋值

var o = {p: 42, q: true};
var {p, q} = o;
console.log(p); // 42
console.log(q); // true

(2)先声明再赋值

var a, b;
({a, b} = {a: 1, b: 2});

注意:赋值语句周围的圆括号 ( ... ) 在使用对象字面量无声明解构赋值时是必须的。

{a, b} = {a: 1, b: 2} 不是有效的独立语法,因为左边的 {a, b} 被认为是一个块而不是对象字面量。

然而,({a, b} = {a: 1, b: 2}) 是有效的,正如 var {a, b} = {a: 1, b: 2}

你的 ( ... ) 表达式之前需要有一个分号,否则它可能会被当成上一行中的函数执行。

(3)对象赋值左侧的属性名作为匹配模式,属性值作为变量

左侧属性名和变量名不同名

let {p:a, q:b} = {p:1, q:2};
console.log(a, b)  //1 2

 左侧属性名和变量同名

let {a, b} = {a:1, a:2};//  let {a:a, b:b} = {a:1, a:2};
console.log(a, b)   //1 2

 (4)默认值

let {p:a=3, q:b=4} = {p:1, q:undefined};
console.log(a, b);   //1 4
let {a=3, b=4} = {a:1, b:undefined};
console.log(a, b); //1 4

(5)剩余参数的提案已经到第四阶段,不推荐使用

(6)计算属性名

let key = "z";
let {[key]: a} = {z: 1};
console.log(key, a); //"z" 1

什么是计算属性?Object_initializer

let key = "z";
let {[key  + "y"]: a} = {zy: 1};
console.log(key, a); //"z" 1

 (7)无效的标识符作为属性名

标识符:字母、$、下划线开头,可以包含数字

const foo = { 'fizz-buzz': true };
const { 'fizz-buzz': fizzBuzz } = foo;
console.log(fizzBuzz); // "true"

 (8)解构对象时会查找原型链

如果属性不在对象 自身,会向原型链 上查找

const protoObj  = {
  name: "protoObj"
}
const obj = Object.create(protoObj);
obj.a = 1;
obj.b = 2;
let {a, b, name} = obj;
console.log(a,b,name);  //1 2 "protoObj"

(9)从 函数实参中提取数据

函数接收对象作为参数, 可以通过该对象的解构,提取数据

function userId({id}) {
  return id;
}

function whois({displayName, fullName: {firstName: name}}){
  console.log(displayName + " is " + name);
}

var user = { 
  id: 42, 
  displayName: "jdoe",
  fullName: { 
      firstName: "John",
      lastName: "Doe"
  }
};

console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"

采用的思路是:函数的形参作为解构对象的左侧内容,函数的实参作为解构对象的右侧具体对象,通过匹配关系进行解构,得到需要的值。

原始值的解构

数字、布尔值和字符串,根据包装类的特性,通过对象解构;同时,ES6特性中,字符串可以解构为数组。

let {toString: toStr} = 123;
console.log(toStr === Number.prototype.toString) //true

let {toString: toS} = true;
console.log(toS === Boolean.prototype.toString) //true

let {length: len} = "xyz";
console.log(len); //3

let [a, b, c] = "xyz";
console.log(a,b,c); // x y z

for of迭代和解构

该实例的实现,是对解构赋值的灵活应用,不管以任何形式得到的数据(对象或数组),都可以通过解构赋值,得到对应的值

var people = [
  {
    name: 'Mike Smith',
    family: {
      mother: 'Jane Smith',
      father: 'Harry Smith',
      sister: 'Samantha Smith'
    },
    age: 35
  },
  {
    name: 'Tom Jones',
    family: {
      mother: 'Norah Jones',
      father: 'Richard Jones',
      brother: 'Howard Jones'
    },
    age: 25
  }
];

for (var {name: n, family: {father: f}} of people) {
  console.log('Name: ' + n + ', Father: ' + f);
}

// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"

实例:解构嵌套对象数组

const metadata = {
  title: 'Scratchpad',
  translations: [
    {
      locale: 'de',
      localization_tags: [],
      last_edit: '2014-04-14T08:43:37',
      url: '/de/docs/Tools/Scratchpad',
      title: 'JavaScript-Umgebung'
    }
  ],
  url: '/en-US/docs/Tools/Scratchpad'
};

let {
  title: englishTitle, // rename
  translations: [
    {
       title: localeTitle, // rename
    },
  ],
} = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle);  // "JavaScript-Umgebung"

 思考

数组和对象的解构引发的思考:

数组是有序列表,通过左边的index索引值找到对应的变量,通过右边的index索引值找到对应的值,然后进行匹配赋值。

而对象,通过左边的属性名找到对应的属性值变量,通过右边的属性名找到对应的属性值,然后进行匹配赋值。

兼容性:Edge 14

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值