ECMAScript 6學習(二)

本人是android開發的,由于最近React Native的火熱,再加上自己完全不懂JS的語法,俗話說的好"落后就要挨打",雖然不知道誰說的,不過很有道理.

學習書籍《ECMAScript 6 入門 》

解構賦值


變量的解構賦值

ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(Destructuring)。

以前,為變量賦值,只能直接指定值。

let a=1;

let b=2;

let c=3;

ES6允許寫成下面這樣。

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

上面代碼表示,可以從數組中提取值,按照對應位置,對變量賦值。

本質上,這種寫法屬于“模式匹配”,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值。

這就是解構賦值

數組解構

如果解構不成功,變量的值就等于undefined。

let [foo] = [];

let [bar,foo] = [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 接口(最后一個表達式)。(此為書上的書面語言,其中Iterator(迭代器)接口,也就是類似于java 中的List和set集合的對象);

比如下面的代碼

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

x // "a"

其中的Set對象就是具備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是一個 Generator 函數(參見《Generator 函數》一章),原生具有 Iterator 接口。解構賦值會依次從這個接口獲取值。

yield 的作用是可以保存結果并返回,下次繼續運行

即 一遇到yield 相當于java 中的return

區別在于 yield 是再次調用方法是會在返回位置繼續執行下去

yield只能在 Generator 生成器中才能使用

?function* xxx();

?function 關鍵字后面有個*號 就是Generator生成器;

對象解構

解構不僅可以用于數組,還可以用于對象。

let { foo, bar } = { foo: "aaa", bar: "bbb" };

foo // "aaa"

bar // "bbb"

好了,這就是對象解構;

啥?哪個是對象?

我剛開始是懵逼的,這那里有什么對象?

好吧,仔細看看

{

? foo:"aaa",

? bar:"bbb"

}

是不是感覺好熟悉?這特么不是json串嗎?

沒錯,ES6的對象就是json串對象;

至于前面那個 let {foo,bar} 其實就是根據相對應的json對象鍵值對取值;


如果變量名與屬性名不一致,必須寫成下面這樣。

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' };

根據個人理解 {foo:baz} 應該是把foo對象的值賦給baz;

繼續往下看

let {foo:foo,bar:bar} = {foo:"aaa",bar:"bbb"};

也就是說,對象的解構賦值的內部機制,是先找到同名屬性,然后再賦給對應的變量。真正被賦值的是后者,而不是前者。

上面代碼中,foo是匹配的模式,baz 才是變量。真正被賦值的是變量 baz,而不是模式 foo。

原來如此

var { foo: baz } = { foo: 'aaa', bar: 'bbb' };

原來 foo只是聲明,也就是相當于java中你聲明一個對象

ABC a = new ABC();

前面的foo 是指代表要獲取這個對象中的foo屬性,獲取的屬性 賦值給 baz變量;

?而像這種寫法

let { foo, bar } = { foo: "aaa", bar: "bbb" };

只是它的簡寫而已;

let {foo:foo,bar:bar} = {foo:"aaa",bar:"bbb"};

對象的解構也可以指定默認值。

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"

沒錯,只要在你要賦值的變量后面加上 "=xxx";就算是指定默認值了

默認值生效的條件是,對象的屬性值嚴格等于undefined。

函數參數的解構賦值

function add([x, y]){

return x + y;

}

add([1, 2]); // 3

上面代碼中,函數add的參數表面上是一個數組,但在傳入參數的那一刻,數組參數就被解構成變量x和y。對于函數內部的代碼來說,它們能感受到的參數就是x和y。

下面是另一個例子。

[1, undefined, 3].map((x = 'yes') => x);

//[1,'yes',3]

map() 用于批量轉換,括號里面可以放一個方法

這句話的意思是用map() 批量對[1, undefined, 3] 這個數組進行處理

處理的方式是

(x = 'yes') => x;

即:

function dkj(x='yes'){

return x;

}

的縮寫,此方式在ECMAScript6才支持;

其中(x='yes')就是x參數的默認值;

解構賦值

1.交換變量的值

let x = 1;

let y = 2;

[x, y] = [y, x];

上面代碼交換變量x和y的值,這樣的寫法不僅簡潔,而且易讀,語義非常清晰

2.從函數返回多個值

函數只能返回一個值,如果要返回多個值,只能將它們放在數組或對象里返回。有了解構賦值,取出這些值就非常方便。

// 返回一個數組

function example() {

? ?return [1, 2, 3];

}

let [a, b, c] = example();

// 返回一個對象

function example() {

? ?return {

? ? ?foo: 1,

? ? ?bar: 2

? ?};

}

let { foo, bar } = example();

3.函數參數的定義

解構賦值可以方便地將一組參數與變量名對應起來。

// 參數是一組有次序的值

function f([x, y, z]) { ... }

f([1, 2, 3]);

// 參數是一組無次序的值

function f({x, y, z}) { ... }

f({z: 3, y: 2, x: 1});

4.提取JSON數據

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.函數參數的默認值

jQuery.ajax = function (url, {

? ?async = true,

? ?beforeSend = function () {},

? ?cache = true,

? ?complete = function () {},

? ?crossDomain = false,

? ?global = true,

? // ... more config

}) {

? // ... do stuff

};

6.遍歷Map結構

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) {

// ...

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容