在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 非結(jié)構(gòu)化賦值
生成器
箭頭函數(shù)
繼續(xù)迭代器
未來(lái)前景
簡(jiǎn)介
非結(jié)構(gòu)化賦值
迭代器和 for-of 循環(huán)
代理
符號(hào)
模版字符串
let 和 const
容器
模塊

非結(jié)構(gòu)化賦值

編者注解:一個(gè)早期 ES6 的版本是由 Firefox 開(kāi)發(fā)工具的工程師尼克?菲茨杰拉德完成,最初以 ES6 非結(jié)構(gòu)化賦值出現(xiàn)在尼克的博客中。

什么是非結(jié)構(gòu)化賦值?

非結(jié)構(gòu)化賦值允許你通過(guò)使用語(yǔ)法規(guī)則將一個(gè)數(shù)組或?qū)ο蟮膶傩苑峙浣o變量,類似于數(shù)組或?qū)ο笪谋?。這個(gè)語(yǔ)法規(guī)則非常簡(jiǎn)單,同時(shí)還表現(xiàn)出比傳統(tǒng)的屬性訪問(wèn)更清晰。

如果沒(méi)有非結(jié)構(gòu)化賦值,你可能運(yùn)用下面的方式訪問(wèn)數(shù)組中的前三個(gè)項(xiàng)目:

var first = someArray[0];
var second = someArray[1];
var third = someArray[2];

當(dāng)有了非結(jié)構(gòu)化賦值,你可以運(yùn)用與上面功能等價(jià)的非結(jié)構(gòu)化賦值代碼,使得代碼更加簡(jiǎn)潔和可讀:

var [first, second, third] = someArray;

SpiderMonkey ( Firefox 提供的 JavaScript 引擎 ) 提供支持大部分的非結(jié)構(gòu)化,但是并不是全部。追蹤 SpiderMonkey 的支持的非結(jié)構(gòu)操作參見(jiàn):https://bugzilla.mozilla.org/show_bug.cgi?id=694100 。

非結(jié)構(gòu)化數(shù)組和迭代器

我們已經(jīng)看到了基于數(shù)組的非結(jié)構(gòu)化賦值的例子。語(yǔ)法的一般形式是:

[ variable1, variable2, ..., variableN ] = array;

這將會(huì)從數(shù)組 array 中對(duì)應(yīng)的項(xiàng)目值賦值給變量1 ( variable1 ) 到變量N ( variableN )。與此同時(shí),如果你想定義你自己的變量,你可以增加 var , let , 或者 const 在賦值語(yǔ)句的最前面。
不像普通的 字符串那樣,模板字符可以覆蓋多行:

ar [ variable1, variable2, ..., variableN ] = array;
let [ variable1, variable2, ..., variableN ] = array;
const [ variable1, variable2, ..., variableN ] = array;

事實(shí)上,用變量 ( variable ) 來(lái)描述是不恰當(dāng)?shù)模驗(yàn)槟氵€可以用深層次的嵌套模式:

var [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
// 1
console.log(bar);
// 2
console.log(baz);
// 3

此外,你可以在非結(jié)構(gòu)化賦值中跳過(guò)一些項(xiàng)目,像下面的代碼一樣:

var [,,third] = ["foo", "bar", "baz"];
console.log(third);
// "baz"

并且你可以通過(guò)“休息”模式,獲得數(shù)組中所有后續(xù)的項(xiàng)目:

var [head, ...tail] = [1, 2, 3, 4];
console.log(tail);
// [2, 3, 4]

當(dāng)你訪問(wèn)數(shù)組中的項(xiàng)目時(shí),產(chǎn)生越界或者訪問(wèn)不存在,你會(huì)得到同樣的索引結(jié)果:未定義的。

console.log([][0]);
// undefined

var [missing] = [];
console.log(missing);
// undefined

注意到基于數(shù)組賦值模式的非結(jié)構(gòu)化賦值通常可以運(yùn)用在任意的迭代器上:

function* fibs() {
  var a = 0;
  var b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(sixth);
// 5

非結(jié)構(gòu)化對(duì)象賦值

非結(jié)構(gòu)化對(duì)象操作允許你將變量綁定到對(duì)象的不同屬性上。你首先指定將要被綁定的屬性,緊跟著將要被賦予綁定值的變量。

var robotA = { name: "Bender" };
var robotB = { name: "Flexo" };

var { name: nameA } = robotA;
var { name: nameB } = robotB;

console.log(nameA);
// "Bender"
console.log(nameB);
// "Flexo"

當(dāng)屬性和變量名稱是相同時(shí),這是一個(gè)有用的語(yǔ)法快捷方式:

var { foo, bar } = { foo: "lorem", bar: "ipsum" };
console.log(foo);
// "lorem"
console.log(bar);
// "ipsum"

并且像非結(jié)構(gòu)化數(shù)組賦值一樣,你可以嵌套和結(jié)合深層次的非結(jié)構(gòu)化:

var complicatedObj = {
  arrayProp: [
    "Zapp",
    { second: "Brannigan" }
  ]
};

var { arrayProp: [first, { second }] } = complicatedObj;

console.log(first);
// "Zapp"
console.log(second);
// "Brannigan"

當(dāng)你非結(jié)構(gòu)化賦值的屬性沒(méi)有被定義,你能得到值:未定義:

var { missing } = {};
console.log(missing);
// undefined

一個(gè)潛在的陷阱你應(yīng)該知道的是當(dāng)你使用非結(jié)構(gòu)化對(duì)象賦值來(lái)分配的變量,但是你沒(méi)有聲明它們:

{ blowUp } = { blowUp: 10 };
// Syntax error

這將發(fā)生因?yàn)?JavaScript 語(yǔ)法告訴引擎去解釋任意的以 { 開(kāi)頭的塊聲明。(舉個(gè)例子, { console } 是一個(gè)有效的塊聲明)。 解決方案是把整個(gè)表達(dá)式的用括號(hào)括起來(lái):

({ safe } = {});
// No errors

對(duì)非對(duì)象、數(shù)組或迭代類型進(jìn)行非結(jié)構(gòu)化賦值

當(dāng)你試圖運(yùn)用非結(jié)構(gòu)化在 null 或者 undefined 上時(shí),你將會(huì)得到一個(gè)類型錯(cuò)誤的值:

var {blowUp} = null;
// TypeError: null has no properties

然而,你可以運(yùn)用非結(jié)構(gòu)化在其它原始的類型中,比如:布爾類型,數(shù)字,和字符串,和未定義 undefinded 類型中:

var {wtf} = NaN;
console.log(wtf);
// undefined

這可能是意想不到的,但在進(jìn)一步檢查中,其實(shí)原因也很簡(jiǎn)單。當(dāng)你運(yùn)用對(duì)象賦值的模式時(shí),被非結(jié)構(gòu)化的值需要被對(duì)象支配。大多數(shù)的類型能夠轉(zhuǎn)換成對(duì)象類型,但是 null 和 undefined 不能轉(zhuǎn)換。當(dāng)你用數(shù)組賦值模式時(shí),被去結(jié)構(gòu)化的值必須是迭代器的形式。

默認(rèn)值

當(dāng)你非結(jié)構(gòu)化的屬性值未被定義時(shí),你還可以提供默認(rèn)值:

var [missing = true] = [];
console.log(missing);
// true

var { message: msg = "Something went wrong" } = {};
console.log(msg);
// "Something went wrong"

var { x = 3 } = {};
console.log(x);
// 3

(編者注釋:這個(gè)默認(rèn)值特性現(xiàn)在已經(jīng)在 Firfox 中實(shí)現(xiàn),但是只支持前兩種形式,不包括第三種。參見(jiàn) bug 932080 : https://bugzilla.mozilla.org/show_bug.cgi?id=932080 )

非結(jié)構(gòu)化的實(shí)際應(yīng)用

參數(shù)定義

作為開(kāi)發(fā)者,我們通常公開(kāi)一些 API 通過(guò)接受一個(gè)有多個(gè)屬性的對(duì)象作為一個(gè)參數(shù),取而代之強(qiáng)制我們的 API 調(diào)用者去記住許多個(gè)別參數(shù)的順序。我們可以利用去結(jié)構(gòu)化來(lái)避免重復(fù)這個(gè)有單一屬性的對(duì)象,當(dāng)我們要引用其中的一個(gè)屬性時(shí):

function removeBreakpoint({ url, line, column }) {
  // ...
}

這是一個(gè)來(lái)自 Firefox 開(kāi)發(fā)工具的簡(jiǎn)化真實(shí)世界的代碼( 在 JavaScript 中被實(shí)現(xiàn) )。我們發(fā)現(xiàn)這種寫法很受歡迎。

配置對(duì)象參數(shù)

擴(kuò)展前面的示例,我們也可以用非結(jié)構(gòu)化賦值給對(duì)象的屬性設(shè)置默認(rèn)值。當(dāng)我們有一個(gè)負(fù)責(zé)提供配置信息的對(duì)象,該對(duì)象的屬性值已經(jīng)有合理的默認(rèn)值,用非結(jié)構(gòu)化給對(duì)象設(shè)置默認(rèn)值就顯得很有幫助了。舉個(gè)例子, jQuery 的 ajax 函數(shù)將一個(gè)配置對(duì)象作為它的第二個(gè)參數(shù),并且被寫為:

jQuery.ajax = function (url, {
  async = true,
  beforeSend = noop,
  cache = true,
  complete = noop,
  crossDomain = false,
  global = true,
  // ... more config
}) {
  // ... do stuff
};

這樣做避免了對(duì)于這個(gè)配置對(duì)象的每個(gè)屬性操作重復(fù): var foo = config.foo || theDefaultFoo。

( 編者注解:不幸地是,對(duì)象的默認(rèn)值這種速寫語(yǔ)法在 Firefox 中還未實(shí)現(xiàn)。我知道,我們已經(jīng)用了一些段落來(lái)學(xué)習(xí)關(guān)于非結(jié)構(gòu)化賦值的知識(shí)。最新更新參見(jiàn) [bug 932080]( https://bugzilla.mozilla.org/show_bug.cgi?id=932080) )

ES6 的迭代協(xié)議

ECMAScript 6 還定義了一個(gè)迭代協(xié)議,在這里我們主要討論早起的迭代協(xié)議。當(dāng)?shù)?Map 類型時(shí),你得到一些列的 [key, value] 對(duì)。我們可以通過(guò)非結(jié)構(gòu)化這些對(duì),來(lái)獲得鍵和值:

var map = new Map();
map.set(window, "the global");
map.set(document, "the document");

for (var [key, value] of map) {
  console.log(key + " is " + value);
}
// "[object Window] is the global"
// "[object HTMLDocument] is the document"

只在鍵上面迭代:

for (var [key] of map) {
  // ...
}

或者只在值上面迭代:

for (var [,value] of map) {
  // ...
}

多個(gè)返回值

盡管多個(gè)返回值沒(méi)有內(nèi)置到語(yǔ)言本體中,但是也并不需要將返回值內(nèi)置,因?yàn)槟憧梢苑祷匾粋€(gè)數(shù)組或者非結(jié)構(gòu)化結(jié)果:

function returnMultipleValues() {
  return [1, 2];
}
var [foo, bar] = returnMultipleValues();

或者,你也可以用一個(gè)對(duì)象為容器和指定返回值:

function returnMultipleValues() {
  return {
    foo: 1,
    bar: 2
  };
}
var { foo, bar } = returnMultipleValues();

這兩種模式最終比持有臨時(shí)容器要好:

function returnMultipleValues() {
  return {
    foo: 1,
    bar: 2
  };
}
var temp = returnMultipleValues();
var foo = temp.foo;
var bar = temp.bar;

或者使用連續(xù)地傳遞模式:

function returnMultipleValues(k) {
  k(1, 2);
}
returnMultipleValues((foo, bar) => ...);

導(dǎo)入 COMMONJS 模塊

仍然不想用 ES6 模塊?還想用 COMMONJS 模塊?沒(méi)問(wèn)題!當(dāng)導(dǎo)入一些 COMMONJS 模塊 X,這是很顯然 X 導(dǎo)入一些比你打算使用的函數(shù)更多的函數(shù)。通過(guò)非結(jié)構(gòu)化賦值的方式,你可以顯式的導(dǎo)入你需要用到的函數(shù),從面避免命名空間的污染:

const { SourceMapConsumer, SourceNode } = require("source-map");

結(jié)論

因此,正如你所看到的,非結(jié)構(gòu)化賦值在許多場(chǎng)景中是有用的。在 Mozilla 我們已經(jīng)有了很多關(guān)于非結(jié)構(gòu)化賦值的經(jīng)驗(yàn)。多年前,Lars Hansen 就已經(jīng)將 JS 非結(jié)構(gòu)化賦值引入到了 opera 中,Brendan Eich 稍后也將在 Firefox 中增加非結(jié)構(gòu)化賦值。它會(huì)被引入在 Firefox 2 版本中。因此我們知道非結(jié)構(gòu)化在你每天使用的語(yǔ)言當(dāng)中,安靜地使你的代碼變得簡(jiǎn)潔和清晰。

更新非結(jié)構(gòu)化賦值來(lái)遵守 ES6 一直是一個(gè)團(tuán)隊(duì)努力的結(jié)果。尤其感謝 Tooru Fujisawa (arai) and Arpad Borsos (Swatinem) 的杰出貢獻(xiàn)。

支持非結(jié)構(gòu)化賦值的 Chrome 當(dāng)前正在開(kāi)發(fā)與此同時(shí)其他瀏覽器無(wú)疑也會(huì)增加支持非結(jié)構(gòu)化賦值操作。現(xiàn)在來(lái)說(shuō),如果你想在 Web 上運(yùn)用非結(jié)構(gòu)化,你需要用到 Babel 或者 Traceur 。

上一篇:簡(jiǎn)介下一篇:符號(hào)