本人是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) {
// ...
}