名词

1 解构:

从数组或对象中提取值,给变量赋值这被称为解构
解构赋值的变量都会重新声明
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错

关键词 模式匹配解构不成功不完全解构解构赋值允许指定默认值 - ES6 允许模式匹配给变量值、set 结构用于数组结构赋值数组结构赋值对象结构赋值函数参数结构赋值圆括号的使用情况字符串结构赋值

    • 模式匹配: 等号两边模式相同,左边的变量就会被赋予对应的值。如果解构不成功,变量就会被赋值 undefined(如下例子),不完全解构 依然是解构成功的情况(如下例)
      不完全解构:指等号左边的模式只能匹配一部分等号右边的数组

1.1 数组解构赋值


let [a, b, c] = [1, 2, 3]
a//1
b//2
c//3

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo //1
bar // 2
baz // 3

let [ , , third] ["foo", "bar", "baz"]
third // 'bar'

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

//===========解构不成功的例子/解构不成功的例子/解构不成功的例子/解构不成功的例子===================
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

let [foo] = []
foo// undefined

let [bar, foo] = [1];
bar//1
foo // undefined

//==========================不完全解构的例子=====================================
let [x,y]=[1,2,3]
x//1
y//2

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

注意 等号右边不是数组 就会报错(如下例子)

let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
//因为等号右边的值,要么转为对象以后不具备 Iterator 接口(前五个表达式),要么本身就不具备 Iterator 接口(最后一个表达式)
//

//但是 let {foo:3}={}  不会报错,因为使用了默认值
    • 对于 Set 结构,也可以使用数组的解构赋值
let [x,y,z]=new set(['a','b','c'])
x//'a'
y//'b'
z//'c'

1.1.2默认值

解构函数允许指定默认值
ES6 使用严格模式(===) 判读是否有值,需要严格等于 undefined ,如果一个数组中的数值不严格等于 undefined 默认值时不会生效的

如果默认值是一个表达式,该表达式时惰性求值的,需要用到的时候才会求值

默认值可以引用解构赋值的其他变量,但前提时该被引用的变量必须提前声明

例如

let [foo=true]=[]
foo // true
let[x,y='b']=['a']
x // 'a'
y //'b'

let [foo='oo']=[undefined]
foo // ‘oo'

let [frr='oo']=[null]
foo// null  因为 null 不严格等于undefined


function f() {
 console.log('aaa');
}
let [x = f()] = [1];
x // 1  这里的发f() 永远不会被调用,因为当默认值时表达式时时惰性求值,只用被需要的时候才会求值,
//而这里数值中的数值时1 因此默认值不起作用,f()永远不被需要

let [x = 1, y = x] = []; // x=1; y=1   y引用x 时,x 已经被提前声明 且x符合默认赋值
let [x = 1, y = x] = [2]; // x=2; y=2  y引用x 时,x 已经被提前声明 x 解构赋值 2,y 又引用的x
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ref  报错   x引用y y没有被提前声明,故报错


1.2 对象的解构赋值

  • 数组解构赋值与对象解构赋值,不同。数组的元素是按照次序排列的,变量的取值由它的位置决定;而对象的属性没有顺序,变量的取值必须与属性同名,才能取到正确的值
    注意点
    • 什么是匹配模式,什么是真正的变量 对象解构赋值的内部机制,先找到同名属性,在赋值给对应变量,真正赋值的是变量而不是匹配模式
    • ,变量的声明和赋值是一体的。对于letconst 来说,变量不能重新声明,所以一旦赋值的变量以前声
      明过,就会报错 不过,因为var命令允许重新声明
let { bar, foo } = { foo: "aaa", bar: "bbb"}
 foo // "aaa"
bar // "bbb"
// 上面那个例子相当于
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };

let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
//变量名与属性名不一样式要写成这样
var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world

let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"
let baz;
let {bar: baz} = {bar: 1}; // SyntaxError: Duplicate declaration "baz"


//下面这样写才行,这里的 ()不能省略 因为解析器会将起首的大括号,理解成一个代码块,而不是
赋值语句
let foo;
({foo} = {foo: 1}); // 成功
let baz;
({bar: baz} = {bar: 1}); // 成功
    • 和数组一样,解构也可以用于嵌套结构的对象
let obj = {
 p: [
 'Hello',
 { y: 'World' }
 ]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
//这时 p 是模式,不是变量,因此不会被赋值




loc: {
 start: {
 line: 1,
 column: 5
 }
 }
};
var { loc: { start: { line }} } = node;
line // 1
loc // error: loc is undefined
start // error: start is undefined
//,只有 line 是变量, loc 和 start 都是模式,不会被赋值


let obj={ };
let arr=[ ];
({foo:obj.prop, bar:arr[0]})={foo:123,bar:true}
obj // {prop:123}
arr //[true]
    • 对象的解构也可以指定默认值 :默认值生效的条件是,对象的属性值严格等于 undefined
var {x = 3} = {};
x // 3
var {x, y = 5} = {x: 1};
x // 1
y // 5
var {x:y = 3} = {};
y // 3
var {x:y = 3} = {x: 5};
y // 5
var { message: msg = 'Something went wrong' } = {};
msg // "Something went wrong
var {x = 3} = {x: undefined};
x // 3

var {x = 3} = {x: null};
x // null

    • 如果解构模式式嵌套的对象,而子对象所在的父对象属性不存在,那么将会报错
// 报错
let {foo: {bar}} = {baz: 'baz'};

    • 如果将一个已经声明的变量用于解构赋值时,必须非常小心 ,必须* 用 () 将器括起来*
let x;
{x} = {x: 1};// 会报错,因为将首起为{ 的解析成代码块

// 正确的写法
({x} = {x: 1});

      • 解构赋值允许,等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式
({}={foo:true,bar:'ooo'})
({} = [true, false]);
({} = 'abc');
({} = []);
    • 对象的解构赋值,可以很方便的将现有对象的方法赋值给莫变量
let{sin,cos,log}=Math
    • 数组时特殊的对象,因此可以将数组进行对象属性的解构
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3

1.3. 字符串的解构赋值

    • 类似数组的对象都有一个 length 属性,因此还可以对这个属性解构赋值
let {length : len} = 'hello';
len // 5

1.4函数参数的解构赋值

function add([x, y]){
  return x + y;
}add([1, 2]); // 3


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


function 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]
//函数 move 的参数是一个对象,通过对这个对象进行解构,得到变量 x 和 y 的值。如果解构失败, x 和 y 等于默认
值




function move({x, y} = { x: 0, y: 0 }) {
 return [x, y];
}
// 解构赋值的默认值通常是放在等号左边的,这个实际上是没有默认值的,而是解构赋值,其实际上这个函数参数是解构赋值的,可以看做 function move({x: 0, y: 0 }) {
 return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined] // 这里y 就没有定义

1.5 圆括号的使用情况

  • 不能再下面三种情况下使用
    • 1 赋值语句中,不能将整个模式或嵌套模式中的一层放在圆括号中
    • 2 变量声明语句中不能带有圆括号
    • 3 函数参数中,模式不能带有圆括号
      如下例都不对
//一下全部报错
({ p: a }) = { p: 42 };  // 报错,原因在赋值语句中共将整个模式放在圆括号中
([a]) = [5];  // 报错,原因在赋值语句中共将整个模式放在圆括号中
[({ p: a }), { x: c }] = [{}, {}];  //赋值语句中,不能将嵌套模式中的一层放在圆括号中


function f([(z)]) { return z; }  // 报错原因 函数参数也属于变量声明,变量声明语句中不能带有圆括号

let [(a)] = [1]; // 变量声明语句中不能带有圆括号
let {x: (c)} = {};// 变量声明语句中不能带有圆括号
let ({x: c}) = {};// 变量声明语句中不能带有圆括号
let {(x: c)} = {};// 变量声明语句中不能带有圆括号
let {(x): c} = {};// 变量声明语句中不能带有圆括号
let { o: ({ p: p }) } = { o: { p: 2 } }; // 变量声明语句中不能带有圆括号
  • 只有一种情况可以使用圆括号
    赋值语句的非模式部分可以使用圆括号
    注意下面例子之所以对,是因为同时没有没有变量声明
[(b)] = [3]; // 正确  
({ p: (d) } = {}); // 正确, 注意这里必须用,这里如果不用圆括号,js 会将首期的{}解析成代码块
[(parseInt.prop)] = [3]; // 正确

1.6 结构赋值的用途

  • 变量交换
  • 函数返回多个值,取值的时候比较方便
  • 函数参数定义时,可以方便的把一组参数与变量名对应起来
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
  • 提取JSON数据
  • 函数参数的默认值================zanshibu能体会
  • 遍历Map结构
  • 输入模块的指定方法

2 set 解构 、Map结构

例如:

new set(['a','b','c'])
var map = new Map();

map结构原生支持 iterator 接口 配合变量的结构赋值,获取 键名、键值 非常方便

var map=new Map()
map.set('first','hello')
map.set('seconed','world')

for(let[key,value]of map){
console.log(key +'is'+value)
}
// first is hello
// second is world



// 获取键名
for (let [key] of map) {
 // ...
}
// 获取键值
for (let [,value] of map) {
 // ...
}

3 Iterator 接口

定义:为各种数据结构提供统一的访问机制,任何数据只要部署了iterator接口,就可以完成遍历操作
任何部署了 iterator 接口的对象,都可以用 for...of 循环遍历

4对象扩展

你可能感兴趣的:(名词)