ホームページ >ウェブフロントエンド >jsチュートリアル >ES6 バージョンの JavaScript_Basics での割り当ての構造化の解析

ES6 バージョンの JavaScript_Basics での割り当ての構造化の解析

WBOY
WBOYオリジナル
2016-05-16 15:48:331330ブラウズ

代入の分割とは何ですか?

代入を分割すると、配列またはオブジェクトのリテラルと同様の構文を使用して、配列およびオブジェクトのプロパティ値を一連の変数に割り当てることができます。この構文は非常に簡潔で、従来のプロパティ アクセスよりも明確です。

構造化代入を使用せずに配列の最初の 3 つの項目にアクセスします:

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

分割代入を使用すると、対応するコードがより簡潔で読みやすくなります。

var [first, second, third] = someArray;
 
var [first, second, third] = someArray;

SpiderMonkey (Firefox の JavaScript エンジン) はすでに、代入の構造化のほとんどの機能をサポートしていますが、完全にはサポートしていません。
配列と反復可能なオブジェクトの代入の構造化

上で配列の構造化代入の例を見てきましたが、この構文の一般的な形式は次のとおりです。

[ variable1, variable2, ..., variableN ] = array;
 
[ variable1, variable2, ..., variableN ] = array;
これにより、配列内の対応する項目が変数 1 から変数 N に順番に割り当てられます。変数を同時に宣言する必要がある場合は、構造化式の前に var、let、または const キーワードを追加できます。


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

実際には、任意の深さにネストできます:


var [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
// 1
console.log(bar);
// 2
console.log(baz);
// 3
 
var [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
// 1
console.log(bar);
// 2
console.log(baz);
// 3
また、配列内の特定の項目をスキップすることもできます:


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

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

Rest 式を使用して、配列内の残りの項目をキャプチャすることもできます。


var [head, ...tail] = [1, 2, 3, 4];
console.log(tail);
// [2, 3, 4]
 
var [head, ...tail] = [1, 2, 3, 4];
console.log(tail);
// [2, 3, 4]
配列が範囲外になった場合、または配列内に存在しない項目にアクセスした場合は、配列インデックスを介してアクセスした場合と同じ値 (未定義) が取得されます。


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

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

配列の構造化と代入の方法は、走査可能なオブジェクトにも適用されることに注意してください。


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

オブジェクトの代入を分割しています

オブジェクトの構造化代入を使用すると、変数をオブジェクトのさまざまなプロパティ値にバインドできます。バインドするプロパティの名前を指定し、その後にバインドする変数を指定します:


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

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

console.log(nameA);
// "Bender"
console.log(nameB);
// "Flexo"
 
var robotA = { name: "Bender" };
var robotB = { name: "Flexo" };
 
var { name: nameA } = robotA;
var { name: nameB } = robotB;
 
console.log(nameA);
// "Bender"
console.log(nameB);
// "Flexo"

バインドされた属性名が属性値を受け取る変数名と同じ場合、別の構文糖衣が存在します:


var { foo, bar } = { foo: "lorem", bar: "ipsum" };
console.log(foo);
// "lorem"
console.log(bar);
// "ipsum"
 
var { foo, bar } = { foo: "lorem", bar: "ipsum" };
console.log(foo);
// "lorem"
console.log(bar);
// "ipsum"
配列と同様に、ネストすることもできます:


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

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

console.log(first);
// "Zapp"
console.log(second);
// "Brannigan"
 
var complicatedObj = {
 arrayProp: [
  "Zapp",
  { second: "Brannigan" }
 ]
};
 
var { arrayProp: [first, { second }] } = complicatedObj;
 
console.log(first);
// "Zapp"
console.log(second);
// "Brannigan"

存在しないプロパティを構造化すると、未定義になります:


var { missing } = {};
console.log(missing);
// undefined
 
var { missing } = {};
console.log(missing);
// undefined
オブジェクトの構造化代入を使用する場合、別の潜在的な落とし穴があります。構造化代入中に変数宣言 (var、let、または const キーワードがありません) がありません。


{ blowUp } = { blowUp: 10 };
// Syntax error
 
{ blowUp } = { blowUp: 10 };
// Syntax error
これは、JavaScript 構文が、{ で始まるステートメントがステートメント ブロックであることをエンジンに伝えるためです (たとえば、{console} は正当なステートメント ブロックです)。解決策は、ステートメント全体を括弧のペアで囲むことです。


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

その他の状況

null または未定義を構造解除しようとすると、型エラーが発生します:

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

ただし、他の基本型 (Boolean、String、Number) を分解すると、未定義になります。


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

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

この結果には驚かれるかもしれませんが、詳しく見てみると、その理由は実はとても簡単です。オブジェクトの構造化と代入を実行すると、構造化されたオブジェクトは Object に強制的に変換されます (null と未定義を除く)。他の型もオブジェクトに強制的に変換できます。配列の構造割り当てを実行する場合、非構造化オブジェクトにはトラバーサが必要です。


デフォルト値

存在しないプロパティのデフォルト値を指定できます:


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

実際の応用 関数パラメータ

開発者として、API ユーザーにいくつかのパラメーターを特定の順序で覚えてもらうのではなく、より柔軟な API を実装するために、複数のプロパティを含むオブジェクトを関数パラメーターとして使用することがよくあります。オブジェクトの構造化割り当てを使用して、パラメーターが使用されるたびに属性にアクセスすることを回避できます。


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

構成オブジェクト

上記の例を改善するには、構造化されるオブジェクトのプロパティにデフォルト値を指定できます。多くの構成項目には適切なデフォルト値があるため、これは構成パラメータとして使用されるオブジェクトにとって非常に実用的です。たとえば、jQuery の ajax メソッドの 2 番目のパラメーターは構成オブジェクトであり、次のように実装できます。


jQuery.ajax = function (url, {
 async = true,
 beforeSend = noop,
 cache = true,
 complete = noop,
 crossDomain = false,
 global = true,
 // ... more config
}) {
 // ... do stuff
};
 
jQuery.ajax = function (url, {
 async = true,
 beforeSend = noop,
 cache = true,
 complete = noop,
 crossDomain = false,
 global = true,
 // ... more config
}) {
 // ... do stuff
};
これにより、var foo = config.foo || theDefaultFoo; のようなコードの重複が回避されます。

反復子とともに使用されます
Map オブジェクトを走査するとき、分割代入を使用して [key, value] を走査できます:


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"

 
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 [key] of map) {
 // ...
}

只遍历值:
for (var [,value] of map) {
 // ...
}

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

複数の値を返す

配列を返し、構造化代入によって戻り値を抽出します:


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

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

または、キーと値のペアのオブジェクトを返します:


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

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

これらはどちらも中間変数を使用するよりも優れています:


function returnMultipleValues() {
 return {
  foo: 1,
  bar: 2
 };
}
var temp = returnMultipleValues();
var foo = temp.foo;
var bar = temp.bar;
 
function returnMultipleValues() {
 return {
  foo: 1,
  bar: 2
 };
}
var temp = returnMultipleValues();
var foo = temp.foo;
var bar = temp.bar;
継続フォームを使用します:


导入 CommonJS 模块的指定部分

还没使用过 ES6 的模块吧,那至少使用过 CommonJS 吧。当导入一个 CommonJS 模块 X 时,模块提供的方法也许多余你实际使用的。使用解构赋值,你可以明确指定你需要使用模块的哪些部分:

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

如果你使用 ES6 的模块机制,你可以看到 import 声明时有一个类似的语法。
结论

我们看到,解构赋值在很多场景下都很实用。在 Mozilla,我们已经有很多经验。Lars Hansen 在 10 年前就向 Opera 引入了解构赋值,Brendan Eich 在稍微晚点也给 Firefox 添加了支持,最早出现在 Firefox 2 中。因此,解构赋值已经渗透到我们每天对 JS 的使用中,悄悄地使我们的代码更简短、整洁。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。