本人是android開發(fā)的,由于最近React Native的火熱,再加上自己完全不懂JS的語(yǔ)法,俗話說(shuō)的好"落后就要挨打",雖然不知道誰(shuí)說(shuō)的,不過很有道理.
學(xué)習(xí)書籍《ECMAScript 6 入門 》
解構(gòu)賦值
變量的解構(gòu)賦值
ES6 允許按照一定模式畏梆,從數(shù)組和對(duì)象中提取值隔披,對(duì)變量進(jìn)行賦值燕鸽,這被稱為解構(gòu)(Destructuring)铺董。
以前远寸,為變量賦值,只能直接指定值球切。
let a=1;
let b=2;
let c=3;
ES6允許寫成下面這樣氓癌。
let [a,b,c] = [1,2,3];
上面代碼表示,可以從數(shù)組中提取值统扳,按照對(duì)應(yīng)位置喘帚,對(duì)變量賦值。
本質(zhì)上咒钟,這種寫法屬于“模式匹配”吹由,只要等號(hào)兩邊的模式相同,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值盯腌。
這就是解構(gòu)賦值
數(shù)組解構(gòu)
如果解構(gòu)不成功溉知,變量的值就等于undefined。
let [foo] = [];
let [bar,foo] = [1];
以上兩種情況都屬于解構(gòu)不成功腕够,foo的值都會(huì)等于undefined级乍。
另一種情況是不完全解構(gòu),即等號(hào)左邊的模式帚湘,只匹配一部分的等號(hào)右邊的數(shù)組玫荣。這種情況下,解構(gòu)依然可以成功大诸。
let [x,y] = [1,2,3];
x ?// 1
y ?// 2
let [a,[b],d] = [1,[2,3],4];
a ?// 1
b ?// 2
d ?// 4
如果等號(hào)的右邊不是數(shù)組捅厂,那么將會(huì)報(bào)錯(cuò)。
// 報(bào)錯(cuò)
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
上面的語(yǔ)句都會(huì)報(bào)錯(cuò)资柔,因?yàn)榈忍?hào)右邊的值焙贷,要么轉(zhuǎn)為對(duì)象以后不具備 Iterator 接口(前五個(gè)表達(dá)式),要么本身就不具備 Iterator 接口(最后一個(gè)表達(dá)式)贿堰。(此為書上的書面語(yǔ)言,其中Iterator(迭代器)接口,也就是類似于java 中的List和set集合的對(duì)象);
比如下面的代碼
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
其中的Set對(duì)象就是具備Iterator接口的(我感覺就是java中的集合);
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 // 5
上面代碼中辙芍,fibs是一個(gè) Generator 函數(shù)(參見《Generator 函數(shù)》一章),原生具有 Iterator 接口羹与。解構(gòu)賦值會(huì)依次從這個(gè)接口獲取值故硅。
yield 的作用是可以保存結(jié)果并返回,下次繼續(xù)運(yùn)行
即 一遇到y(tǒng)ield 相當(dāng)于java 中的return
區(qū)別在于 yield 是再次調(diào)用方法是會(huì)在返回位置繼續(xù)執(zhí)行下去
yield只能在 Generator 生成器中才能使用
即
?function* xxx();
?function 關(guān)鍵字后面有個(gè)*號(hào) 就是Generator生成器;
對(duì)象解構(gòu)
解構(gòu)不僅可以用于數(shù)組,還可以用于對(duì)象纵搁。
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
好了,這就是對(duì)象解構(gòu);
啥?哪個(gè)是對(duì)象?
我剛開始是懵逼的,這那里有什么對(duì)象?
好吧,仔細(xì)看看
{
? foo:"aaa",
? bar:"bbb"
}
是不是感覺好熟悉?這特么不是json串嗎?
沒錯(cuò),ES6的對(duì)象就是json串對(duì)象;
至于前面那個(gè) let {foo,bar} 其實(shí)就是根據(jù)相對(duì)應(yīng)的json對(duì)象鍵值對(duì)取值;
如果變量名與屬性名不一致吃衅,必須寫成下面這樣。
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'
(┬_┬)!!! 這又是什么鬼
var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
根據(jù)個(gè)人理解 {foo:baz} 應(yīng)該是把foo對(duì)象的值賦給baz;
繼續(xù)往下看
let {foo:foo,bar:bar} = {foo:"aaa",bar:"bbb"};
也就是說(shuō)腾誉,對(duì)象的解構(gòu)賦值的內(nèi)部機(jī)制徘层,是先找到同名屬性峻呕,然后再賦給對(duì)應(yīng)的變量。真正被賦值的是后者惑灵,而不是前者山上。
上面代碼中眼耀,foo是匹配的模式英支,baz 才是變量。真正被賦值的是變量 baz哮伟,而不是模式 foo干花。
原來(lái)如此
var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
原來(lái) foo只是聲明,也就是相當(dāng)于java中你聲明一個(gè)對(duì)象
ABC a = new ABC();
前面的foo 是指代表要獲取這個(gè)對(duì)象中的foo屬性,獲取的屬性 賦值給 baz變量;
?而像這種寫法
let { foo, bar } = { foo: "aaa", bar: "bbb" };
只是它的簡(jiǎn)寫而已;
let {foo:foo,bar:bar} = {foo:"aaa",bar:"bbb"};
對(duì)象的解構(gòu)也可以指定默認(rèn)值。
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"
沒錯(cuò),只要在你要賦值的變量后面加上 "=xxx";就算是指定默認(rèn)值了
默認(rèn)值生效的條件是楞黄,對(duì)象的屬性值嚴(yán)格等于undefined池凄。
函數(shù)參數(shù)的解構(gòu)賦值
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
上面代碼中,函數(shù)add的參數(shù)表面上是一個(gè)數(shù)組鬼廓,但在傳入?yún)?shù)的那一刻肿仑,數(shù)組參數(shù)就被解構(gòu)成變量x和y。對(duì)于函數(shù)內(nèi)部的代碼來(lái)說(shuō)碎税,它們能感受到的參數(shù)就是x和y尤慰。
下面是另一個(gè)例子。
[1, undefined, 3].map((x = 'yes') => x);
//[1,'yes',3]
map() 用于批量轉(zhuǎn)換,括號(hào)里面可以放一個(gè)方法
這句話的意思是用map() 批量對(duì)[1, undefined, 3] 這個(gè)數(shù)組進(jìn)行處理
處理的方式是
(x = 'yes') => x;
即:
function dkj(x='yes'){
return x;
}
的縮寫,此方式在ECMAScript6才支持;
其中(x='yes')就是x參數(shù)的默認(rèn)值;
解構(gòu)賦值
1.交換變量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
上面代碼交換變量x和y的值雷蹂,這樣的寫法不僅簡(jiǎn)潔伟端,而且易讀,語(yǔ)義非常清晰
2.從函數(shù)返回多個(gè)值
函數(shù)只能返回一個(gè)值匪煌,如果要返回多個(gè)值责蝠,只能將它們放在數(shù)組或?qū)ο罄锓祷亍S辛私鈽?gòu)賦值萎庭,取出這些值就非常方便霜医。
// 返回一個(gè)數(shù)組
function example() {
? ?return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一個(gè)對(duì)象
function example() {
? ?return {
? ? ?foo: 1,
? ? ?bar: 2
? ?};
}
let { foo, bar } = example();
3.函數(shù)參數(shù)的定義
解構(gòu)賦值可以方便地將一組參數(shù)與變量名對(duì)應(yīng)起來(lái)。
// 參數(shù)是一組有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 參數(shù)是一組無(wú)次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
4.提取JSON數(shù)據(jù)
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
5.函數(shù)參數(shù)的默認(rèn)值
jQuery.ajax = function (url, {
? ?async = true,
? ?beforeSend = function () {},
? ?cache = true,
? ?complete = function () {},
? ?crossDomain = false,
? ?global = true,
? // ... more config
}) {
? // ... do stuff
};
6.遍歷Map結(jié)構(gòu)
var 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
// 獲取鍵名
for (let [key] of map) {
// ...
}
// 獲取鍵值
for (let [,value] of map) {
// ...
}