วงเล็บปีกกาในคำสั่ง `var {…} = …` ทำอะไร?


117

ไม่แน่ใจว่านี่เป็นไวยากรณ์ JS เฉพาะของ Mozilla หรือไม่ แต่ฉันมักพบตัวแปรที่ประกาศด้วยวิธีนี้เช่นในเอกสาร SDK เสริม :

var { Hotkey } = require("sdk/hotkeys");

และใน Chrome Javascript ต่างๆ (ใช้letคำสั่งแทนvar)

let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu }  = Components;

ผมพบว่ามันทำให้เกิดความสับสนมาก แต่ผมไม่สามารถที่จะหาเอกสารใด ๆ เกี่ยวกับไวยากรณ์ทั้งแม้ในMDN


@Blender คุณจะค้นหาโครงสร้างนี้ใน symbolhound.com ได้อย่างไร?
trusktr

1
@trusktr: ช้าไปหน่อย: symbolhound.com/…
Blender

คำตอบสั้น ๆ อยู่ที่นี่: stackoverflow.com/a/45909752/203704
Cliff Hall

ฉันสบายดีกับการแยกโครงสร้างพื้นฐาน อย่างไรก็ตามในตัวอย่างนี้เรากำลังกำหนดค่าให้กับชื่อคุณสมบัติอื่นและไวยากรณ์นั้นสับสนมาก ตรงข้ามกับไวยากรณ์การสร้างวัตถุและทำให้เกิดความสับสนมากขึ้น
Sol

คำตอบ:


72

เป็นคุณลักษณะของ JavaScript 1.7 ทั้งคู่ ตัวแรกคือตัวแปรระดับบล็อก :

letอนุญาตให้คุณประกาศตัวแปร จำกัด ขอบเขตไว้ที่บล็อกคำสั่งหรือนิพจน์ที่จะใช้ ซึ่งแตกต่างจากvarคำหลักซึ่งกำหนดตัวแปรทั่วโลกหรือเฉพาะกับฟังก์ชันทั้งหมดโดยไม่คำนึงถึงขอบเขตการบล็อก

อันที่สองเรียกว่าการทำลายล้าง :

การกำหนดโครงสร้างการทำลายทำให้สามารถดึงข้อมูลจากอาร์เรย์หรืออ็อบเจ็กต์โดยใช้ไวยากรณ์ที่สะท้อนการสร้างอาร์เรย์และอ็อบเจ็กต์ลิเทอรัล
...
สิ่งที่มีประโยชน์อย่างยิ่งอย่างหนึ่งที่คุณสามารถทำได้กับการมอบหมายการทำลายโครงสร้างคือการอ่านโครงสร้างทั้งหมดในคำสั่งเดียวแม้ว่าจะมีสิ่งที่น่าสนใจมากมายที่คุณสามารถทำได้ดังที่แสดงในส่วนที่เต็มไปด้วยตัวอย่างต่อไปนี้

สำหรับผู้ที่คุ้นเคยกับ Python จะคล้ายกับไวยากรณ์นี้:

>>> a, (b, c) = (1, (2, 3))
>>> a, b, c
(1, 2, 3)

รหัสแรกคือชวเลขสำหรับ:

var {Hotkey: Hotkey} = require("sdk/hotkeys");
// Or
var Hotkey = require("sdk/hotkeys").Hotkey;

คุณสามารถเขียนโค้ดชิ้นที่สองใหม่เป็น:

let Cc = Components.classes;
let Ci = Components.interfaces;
let Cr = Components.results;
let Cu = Components.utils;

2
จากการทดสอบของฉันดูเหมือนจะเทียบเท่ากับvar { Hotkey } var { Hotkey: Hotkey }ขอขอบคุณที่ค้นหาเอกสาร!
timdream

@timdream: ฉันมีความรู้สึกว่ามันเป็นแบบนั้น แต่มันแตกต่างจากvar Hotkey = require(...).Hotkeyอย่างไร? หรือเป็นเพียงการบันทึกการกดแป้นพิมพ์?
Blender

ดูเหมือนว่า: - / (ฮิฮิโปรแกรมเมอร์ขี้เกียจเหล่านี้ ... )
timdream

2
นอกจากนี้ยังทำให้ทุกอย่างเป็นความลับมากขึ้นในการใช้ไวยากรณ์ที่ไม่ธรรมดา
trusktr

อันที่สองคือ "Object Destructuring" อ้างอิงจากdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
IcyBrk

80

สิ่งที่คุณกำลังมองหาคือการมอบหมายงานที่ทำลายโครงสร้าง เป็นรูปแบบของการจับคู่รูปแบบเหมือนใน Haskell

การใช้การกำหนดโครงสร้างแบบทำลายคุณสามารถดึงค่าจากอ็อบเจ็กต์และอาร์เรย์และกำหนดให้กับตัวแปรที่ประกาศใหม่โดยใช้อ็อบเจ็กต์และไวยากรณ์ลิเทอรัล สิ่งนี้ทำให้โค้ดมีความกระชับมากขึ้น

ตัวอย่างเช่น:

var ascii = {
    a: 97,
    b: 98,
    c: 99
};

var {a, b, c} = ascii;

รหัสข้างต้นเทียบเท่ากับ:

var ascii = {
    a: 97,
    b: 98,
    c: 99
};

var a = ascii.a;
var b = ascii.b;
var c = ascii.c;

ในทำนองเดียวกันสำหรับอาร์เรย์:

var ascii = [97, 98, 99];

var [a, b, c] = ascii;

สิ่งนี้เทียบเท่ากับ:

var ascii = [97, 98, 99];

var a = ascii[0];
var b = ascii[1];
var c = ascii[2];

คุณยังสามารถแยกและเปลี่ยนชื่อคุณสมบัติอ็อบเจ็กต์ได้ดังนี้:

var ascii = {
    a: 97,
    b: 98,
    c: 99
};

var {a: A, b: B, c: C} = ascii;

สิ่งนี้เทียบเท่ากับ:

var ascii = {
    a: 97,
    b: 98,
    c: 99
};

var A = ascii.a;
var B = ascii.b;
var C = ascii.c;

นั่นคือทั้งหมดที่มีให้


12
+1 สำหรับตัวอย่างการทำลายวัตถุซึ่งมีประโยชน์มาก ตัวอย่าง MDNแสดงเฉพาะ destructuring อาร์เรย์
Blender

@Blender - พวกเขาให้ตัวอย่างการทำลายวัตถุ ดูLooping ข้ามค่าในอาร์เรย์ของวัตถุ
Aadit M Shah

ฉันหมายถึงvar {a, b, c} = ascii;ไวยากรณ์
Blender

ตัวอย่างสุดท้ายนั้นแปลกมากเพราะโดยปกติสิ่งที่อยู่ทางซ้ายของลำไส้ใหญ่คือสิ่งที่กำหนด
Curtis

1

นี่เป็นการกำหนดการทำลายใน Javascript และเป็นส่วนหนึ่งของมาตรฐาน ES2015 มันคลายแพ็กหรือแยกค่าจากอาร์เรย์หรือคุณสมบัติจากอ็อบเจ็กต์เป็นตัวแปรที่แตกต่าง เช่น: Array Destructuring

var foo = ["one", "two", "three"];
//without destructuring
var one = foo[0];
var two = foo[1];
var three = foo[2];

// ด้วยการทำลาย var [หนึ่งสองสาม] = foo

เช่น: Object Destructuring

var o = {p: 42, q: true}; var {p, q} = o;

console.log (P); // 42 console.log (q); // จริง

// กำหนดชื่อตัวแปรใหม่ var {p: foo, q: bar} = o;

console.log (foo); // 42 console.log (บาร์); // จริง


0

มีเอกสารสำหรับletคำชี้แจงเกี่ยวกับ MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/let

letคล้ายกับvarว่ามัน จำกัด ขอบเขตของตัวแปรที่ประกาศไว้ ช่วยให้คุณสามารถประกาศตัวแปรภายในif(){}บล็อก (หรือบล็อกอื่น ๆ ) และกำหนดให้ตัวแปรนั้น "มองเห็นได้" ภายในบล็อกนั้นเท่านั้น (JavaScript จนถึงขณะนี้มีขอบเขตฟังก์ชันและไม่มีขอบเขตการบล็อกเหมือนภาษาอื่น ๆ ส่วนใหญ่) ดังนั้นletโดยพื้นฐานแล้วเป็นการ "แก้ไข" สำหรับสิ่งที่หลายคนมีปัญหา โปรดทราบว่า tihs เป็นคุณลักษณะของ JavaScript 1.7

{Foo}ยังไม่พบอะไรใน


ขออภัยฉันคิดว่าคุณเครื่องถามเกี่ยวกับทั้งสองอย่าง ... google-fu ของฉันทำให้ฉันล้มเหลวเมื่อมันมาถึง{Foo}: /
Jan Hančič

ฉันด้วย: - / Google ไม่จัดทำดัชนี{และ}.
timdream
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.