乐趣区

关于es6:变量的解构赋值

变量的解构赋值:

数组的解构赋值:

依照肯定模式, 从数组和对象中提取对象, 对变量进行赋值, 称为解构.

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

写法属于“模式匹配”: 依照对应地位,对变量赋值

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

解构不胜利: 变量的值就等于 undefined.

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

不齐全解构:

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] = {};

set 构造, 也能够解构赋值

let [x,y,z] = new Set(['a','b','c'])

只有数据结构具备迭代, 都能够解构赋值

默认值

let [foo = true] = []
foo = true

let [x, y='b'] =['a',undefined]
x= a
y = b

当一个数组成员严格等于(===)undefined 的时候, 才采纳默认值([y= ‘b’])

对象的解构赋值

let {foo,bar} = {foo:'aaa',bar:'bbb'}
foo  ='aaa'
bar = 'bbb'

与数组不同的是, 对象没有秩序, 必须于属性同名, 能力取值
解构失败, 变量的值为 undefined

let {bar, foo, baz} = {foo: 'aaa', bar: 'bbb'};
foo // "aaa"
bar // "bbb"
baz //undefined

能够将现有对象的办法, 赋值到某个变量

let {log,sin,cos} = Math

const {log} = console
log('math') = hello

下面代码的例一将 Math 对象的对数、正弦、余弦三个办法,赋值到对应的变量上
例二将 console.log 赋值到 log 变量

变量名与属性名不统一: 真正被赋值的是后者,而不是前者
let {foo:baz} = {foo:’aaa’,bar:’bbb’}

let obj = {first:’hello’,last:’world’}
let {first:f,last:l} = obj
f = hello
l:world

let obj = {p:[“hello”,{y:”world”}]}

let {p:[x,{y}]} = obj
x = ‘hello’
y = “world”

let {p,p:[x,{y}]} = obj
x // “Hello”
y // “World”
p // [“Hello”, {y: “World”}]

三次解构赋值:
const node = {
loc: {

start: {
  line: 1,
  column: 5
}

}
};

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

只有 line 是变量,loc 和 start 都是模式, 不是变量

嵌套赋值:
let obj = {}
let arr = []
({foo:obj.prop,bar:arr[0]} = {foo:123,bar:true})

obj = {prop:123}
arr = [true]

let {foo:{bar}} = {baz:’baz’} // 报错(因为 foo 这时等于 undefined 再取子属性就会报错)

对象的解构赋值能够取到继承的属性:

const obj1= {}
const obj2 = {foo:’bar’}
Object.setPrototypeof(obj1,obj2)
const {foo} = obj1
foo = ‘bar’
setPrototypeof: 设置一个指定的对象的原型 (即外部[[Prototype]] 属性到另一个对象或 null

对象 obj1 的原型对象是 obj2。
foo 属性不是 obj1 本身的属性,而是继承自 obj2 的属性,解构赋值能够取到这个属性。

默认值

var {x:y = 5} = {}
y = 5
var {x:y = 3} = {x = 5}
y = 5

默认值失效的条件是,对象的属性值严格等于 undefined
var {x = 3} = {x = undefined}
x = 3
var {x = 3} = {x = null}
x = null

属性名表达式:
let arr = [1, 2, 3];
let {0 : first, [arr.length – 1] : last} = arr;
first // 1
last // 3

// 谬误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
下面代码的写法会报错,因为 JavaScript 引擎会将 {x} 了解成一个代码块,从而产生语法错误。只有不将大括号写在行首,防止 JavaScript 将其解释为代码块,能力解决这个问题。// 正确的写法
let x;
({x} = {x: 1});

字符串的解构赋值

此时, 字符串被转换成了一个相似数组的对象
const [a,b,c,d,e] = “hello”
a = h
b = e
c = l
d = l
e = o

相似数组都有一个 length 属性, 能够对这个属性解构赋值
let {length : len} = ‘hello’;
len // 5

数值和布尔值的解构赋值

数值和布尔值的包装对象都有 toString 属性,因而变量 s 都能取到值:
let {toString:s} = 123
s === Number.prototype.toString

let {toString:s} = true
s === Boolean.prototype.toString

解构赋值的规定, 只有等号左边的值不是数组或对象, 就先转化为对象.
因为 undefined 和 null 无奈转化为对象, 所以解构会报错

函数参数的解构赋值

function add([x,y]){

return x+y

}
add([1,2])

[[1,2],[3,4]].map(([a,b])=>{a+b})
map: 遍历数组返回一个新数组

对象的解构赋值默认值, 没有应用函数参数的默认值:

function foo({x, y = 0}) {console.log(x, y)
}
foo({}); // undefined 0
foo({x: 0}); // 0 0
foo({x: 1, y: 1}); // 1 1
foo(); // 报错:TypeError: Cannot read property 'x' of undefined
如果函数 foo 调用时没提供参数,变量 x 和 y 不会生成,从而报错。function foo({x, y = 0} = {}) {console.log(x, y)
}
foo({}); // undefined 0
foo({x: 0}); // 0 0
foo({x: 1, y: 1}); // 1 1
foo(); // undefined 0

解释

为函数参数变量 x、y 指定默认值
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]

为函数参数指定默认值{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]

用处

  • 替换变量的值
let x = 1
let y = 2
[x,y] = [y,x]
  • 从函数返回多个值
function example(){return[1,2,3]
}
let [a,b,c] = example()

function example(){return {foo:1,bar:2}
}
let {foo,bar} = example()
  • 函数参数的定义
function f([x,z,y]){...}
f([1,2,3])

function f({x, y, z}) {...}
f({z: 3, y: 2, x: 1});
  • 提取 JSON 数据
let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let {id,status,data:number} = jsonData
number =  [867, 5309]
  • 函数参数的默认值
jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {// ... do stuff};
  • 遍历 map 构造
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {console.log(key + "is" + value);
}
// first is hello
// second is world
  • 输出模块的指定办法

加载模块时,往往须要指定输出哪些办法。解构赋值使得输出语句十分清晰。
const {SourceMapConsumer, SourceNode} = require(“source-map”);

退出移动版