เมื่อใดที่ฉันควรใช้เครื่องมือจัดฟันแบบโค้งสำหรับการนำเข้า ES6


764

ดูเหมือนจะชัดเจน แต่ฉันพบว่าตัวเองสับสนเล็กน้อยเกี่ยวกับเวลาที่จะใช้เครื่องมือจัดฟันแบบโค้งสำหรับนำเข้าโมดูลเดียวใน ES6 ตัวอย่างเช่นในโครงการ React-Native ฉันกำลังทำงานฉันมีไฟล์และเนื้อหาดังต่อไปนี้:

initialState.js
var initialState = {
    todo: {
        todos: [
            {id: 1, task: 'Finish Coding', completed: false},
            {id: 2, task: 'Do Laundry', completed: false},
            {id: 2, task: 'Shopping Groceries', completed: false},
        ]
    }
};

export default initialState;

ใน TodoReducer.js ฉันต้องนำเข้าโดยไม่มีเครื่องหมายปีกกา:

import initialState from './todoInitialState';

หากฉันใส่initialStateวงเล็บปีกกาเป็นหยิกฉันจะได้รับข้อผิดพลาดต่อไปนี้สำหรับรหัสบรรทัดต่อไปนี้:

ไม่สามารถอ่านคุณสมบัติ todo จาก undefined

TodoReducer.js:
export default function todos(state = initialState.todo, action) {
// ...
}

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

แก้ไข:

โพสต์ SO ที่นี่ไม่ตอบคำถามของฉัน แต่ฉันถามเมื่อฉันควรหรือไม่ควรใช้วงเล็บปีกกาสำหรับการนำเข้าโมดูลเดียวหรือฉันไม่ควรใช้วงเล็บปีกกาสำหรับการนำเข้าโมดูลเดียวใน ES6 (เห็นได้ชัดว่าไม่ใช่ กรณีดังที่ฉันได้เห็นการนำเข้าครั้งเดียวพร้อมด้วยเครื่องหมายปีกกาที่ต้องการ



1
ไม่มันแตกต่างกัน ขอบคุณ
TonyGW

คำตอบ:


2262

นี่คือการนำเข้าเริ่มต้น :

// B.js
import A from './A'

ใช้งานAได้หากมีการส่งออกเริ่มต้นเท่านั้น :

// A.js
export default 42

ในกรณีนี้ไม่สำคัญว่าคุณจะกำหนดชื่ออะไรเมื่อนำเข้า:

// B.js
import A from './A'
import MyA from './A'
import Something from './A'

เพราะมันมักจะแก้ไขสิ่งที่เป็นการส่งออกเริ่มต้นAของ


นี่คือการนำเข้าชื่อที่เรียกว่าA :

import { A } from './A'

ใช้งานได้เฉพาะถ้าAมีการเอ็กซ์ปอร์ตAแบบมีชื่อที่เรียกว่า :

export const A = 42

ในกรณีนี้ชื่อมีความสำคัญเนื่องจากคุณกำลังนำเข้าสิ่งที่ต้องการด้วยชื่อการส่งออก :

// B.js
import { A } from './A'
import { myA } from './A' // Doesn't work!
import { Something } from './A' // Doesn't work!

เพื่อให้งานเหล่านี้คุณจะต้องเพิ่มการส่งออกที่มีชื่อที่สอดคล้องกันไปยังA:

// A.js
export const A = 42
export const myA = 43
export const Something = 44

โมดูลสามารถมีการส่งออกเริ่มต้นได้เพียงหนึ่งรายการเท่านั้น แต่สามารถส่งออกได้หลายชื่อตามที่คุณต้องการ (ศูนย์หนึ่งสองหรือหลายรายการ) คุณสามารถนำเข้าทั้งหมดเข้าด้วยกัน:

// B.js
import A, { myA, Something } from './A'

ที่นี่เรานำเข้าการส่งออกเริ่มต้นเป็นAและส่งออกที่มีชื่อเรียกว่าmyAและSomethingตามลำดับ

// A.js
export default 42
export const myA = 43
export const Something = 44

นอกจากนี้เรายังสามารถกำหนดชื่อที่ต่างกันทั้งหมดเมื่อนำเข้า:

// B.js
import X, { myA as myX, Something as XSomething } from './A'

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

นี่เป็นคำแนะนำที่ดีสำหรับโมดูล ES ซึ่งอธิบายความแตกต่างระหว่างการส่งออกเริ่มต้นและการตั้งชื่อ


4
มีความหายนะที่จะมีโมดูลมีการส่งออกexport const myA = 43; export const Something = 44;เป็นรายบุคคล เช่นเดียวกับexport default { myA, Something }? ดังนั้นเมื่อคุณนำเข้าคุณสามารถทำได้import A from './A';ทุกอย่างในโมดูลหรือ import { Something } from './A';เพื่อให้คุณได้รับโมดูลบางอย่างเท่านั้น
Michael

12
มันเป็นดี import * as AllTheThingsแต่มีอยู่แล้วไวยากรณ์สำหรับการส่งออกโลภชื่อทั้งหมดลงในวัตถุเดียว:
Dan Abramov

82
อธิบายอย่างชัดเจน! ฉันหวังว่าฉันจะสามารถโหวตคำตอบนี้ได้สองครั้ง
Willa

7
สิ่งที่เกี่ยวกับ this- หรือimport 'firebase/storage'; import 'rxjs/add/operator/map';สิ่งนี้กำลังทำอะไรอยู่?
kyw

9
@kyw: จะดำเนินการโมดูล แต่ไม่สนใจค่าที่ส่งออก มีประโยชน์สำหรับผลข้างเคียง
Dan Abramov

84

ฉันจะบอกว่ามีสัญกรณ์ติดดาวสำหรับimportคำหลัก ES6 ที่ควรกล่าวถึง

ป้อนคำอธิบายรูปภาพที่นี่

ถ้าคุณพยายามที่จะ console log Mix:

import * as Mix from "./A";
console.log(Mix);

คุณจะได้รับ:

ป้อนคำอธิบายรูปภาพที่นี่

เมื่อใดที่ฉันควรใช้เครื่องมือจัดฟันแบบโค้งสำหรับการนำเข้า ES6

วงเล็บมีสีทองเมื่อคุณต้องการส่วนประกอบเฉพาะจากโมดูลซึ่งทำให้มีขนาดเล็กลงสำหรับผู้ประกอบการเช่น webpack


4
ภาพของคุณเป็นแผ่นโกงที่สมบูรณ์แบบสำหรับคำตอบเฉพาะนี้
Rodrirokr

1
มีimport * as Mix from "./A";และimport A as Mix from "./A";เดียวกันได้หรือไม่
Shafizadeh

40

คำตอบที่แดน Abramov ข้างต้นอธิบายเกี่ยวกับการส่งออกเริ่มต้นและการส่งออกชื่อ

จะใช้อะไร

การอ้างอิง David Herman : ECMAScript 6 สนับสนุนรูปแบบการส่งออกเดี่ยว / ค่าเริ่มต้นและให้ไวยากรณ์ที่หอมหวานเพื่อนำเข้าค่าเริ่มต้น การนำเข้าการส่งออกที่มีชื่อสามารถและควรกระชับน้อยลงเล็กน้อย

อย่างไรก็ตามใน TypeScript ชื่อการส่งออกได้รับการสนับสนุนเนื่องจาก refactoring ตัวอย่างถ้าคุณเริ่มต้นส่งออกชั้นเรียนและเปลี่ยนชื่อชื่อชั้นจะเปลี่ยนเฉพาะในไฟล์นั้นและไม่ได้อยู่ในการอ้างอิงอื่น ๆ ด้วยชื่อชั้นส่งออกชื่อจะถูกเปลี่ยนชื่อในการอ้างอิงทั้งหมด การส่งออกที่มีชื่อเป็นที่ต้องการสำหรับสาธารณูปโภคเช่นกัน

โดยรวมใช้สิ่งที่คุณต้องการ

เพิ่มเติม

การส่งออกเริ่มต้นเป็นจริงการส่งออกที่มีชื่อพร้อมชื่อเริ่มต้นดังนั้นการส่งออกเริ่มต้นจึงสามารถนำเข้าเป็น:

import {default as Sample} from '../Sample.js';

2
Additionalบรรทัดเป็นข้อมูลที่ดี ไม่ได้ทำให้รู้สึกว่าคุณกำลังส่งออกโดยไม่ต้องกำหนดชื่อเหมือนimport A from './A' export default 42
PGT

8
โปรดอย่าตีความคำพูดของเดวิดเฮอร์แมนผิด มันไม่ได้หมายความว่า " มันเป็นที่ชื่นชอบที่จะเสมอใช้การส่งออก / เริ่มต้นเดียวใน ES6 " แต่ " เพราะการส่งออกเพียงครั้งเดียวเป็นเรื่องธรรมดาดังนั้น ES6 สนับสนุนค่าเริ่มต้นที่ดีที่สุดและเราให้พวกเขามีไวยากรณ์ที่หอมหวาน "
Bergi

15

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

// bar.js
module = {};

module.exports = { 
  functionA: () => {},
  functionB: ()=> {}
};

 // really all that is is this:
 var module = { 
   exports: {
      functionA, functionB
   }
  };

// then, over in foo.js

// the whole exported object: 
var fump = require('./bar.js'); //= { functionA, functionB }
// or
import fump from './bar' // same thing, object functionA and functionB props


// just one prop of the object
var fump = require('./bar.js').functionA;

// same as this, right?
var fump = { functionA, functionB }.functionA;

// and if we use es6 destructuring: 
var { functionA } =  { functionA, functionB };
// we get same result

// so, in import syntax:
import { functionA } from './bar';

9

เพื่อให้เข้าใจถึงการใช้เครื่องหมายปีกกาในimportคำสั่งก่อนอื่นคุณต้องเข้าใจแนวคิดของการทำลายล้างที่แนะนำในES6

  1. การทำลายวัตถุ

    var bodyBuilder = {
      firstname: 'Kai',
      lastname: 'Greene',
      nickname: 'The Predator'
    };
    
    var {firstname, lastname} = bodyBuilder;
    console.log(firstname, lastname); //Kai Greene
    
    firstname = 'Morgan';
    lastname = 'Aste';
    
    console.log(firstname, lastname); // Morgan Aste
  2. การทำลายอาร์เรย์

    var [firstGame] = ['Gran Turismo', 'Burnout', 'GTA'];
    
    console.log(firstGame); // Gran Turismo

    ใช้รายการที่ตรงกัน

      var [,secondGame] = ['Gran Turismo', 'Burnout', 'GTA'];
      console.log(secondGame); // Burnout

    การใช้ตัวดำเนินการสเปรด

    var [firstGame, ...rest] = ['Gran Turismo', 'Burnout', 'GTA'];
    console.log(firstGame);// Gran Turismo
    console.log(rest);// ['Burnout', 'GTA'];

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

สมมติว่าคุณมีโมดูลที่เรียกว่า module.js

    export const printFirstname(firstname) => console.log(firstname);
    export const printLastname(lastname) => console.log(lastname);

คุณต้องการที่จะนำเข้าฟังก์ชั่นการส่งออกเป็นindex.js;

    import {printFirstname, printLastname} from './module.js'

    printFirstname('Taylor');
    printLastname('Swift');

คุณยังสามารถใช้ชื่อตัวแปรอื่นได้

    import {printFirstname as pFname, printLastname as pLname} from './module.js'

    pFname('Taylor');
    pLanme('Swift');

เนื่องจากคุณแสดงการเปรียบเทียบกับการทำลายล้างฉันจะเพิ่มการเปรียบเทียบการทำลายที่เทียบเท่ากับความคิดเห็นสุดท้ายของคุณ: import {printFirstname as pFname, printLastname as pLname} from './module.js'เท่ากับ:var foo = {printFirstname: 'p_f_n', printLastname: 'p_l_n'}; var { printFirstname:pFname, printLastname: pLname } = foo; pFname('Taylor'); pLname('Swift');
Adam Moisa

แฟนเพาะกาย?
Tushar Pandey

@TusharPandey ฉันเป็นผู้สร้างร่างกาย
theTypan

1
ฉันคิดว่าในคำอธิบายใด ๆ ของการนำเข้าและเมื่อใดที่จะใช้ curlys กับการไม่ใช้มันหากคุณไม่ได้กล่าวถึงการทำลายวัตถุคุณจะไม่ได้ให้คำอธิบายที่ดีที่สุด เมื่อฉันเรียนรู้เกี่ยวกับการทำลายล้างฉันไม่เคยคิดเลยว่าทำไมฉันจึงใช้หยิกอีกต่อไป
Eric Bishard

6

ES6โมดูลสรุป:

การส่งออก:

คุณมีการส่งออก 2 ประเภท:

  1. การส่งออกที่มีชื่อ
  2. การส่งออกเริ่มต้นสูงสุด 1 ต่อโมดูล

ไวยากรณ์:

// Module A
export const importantData_1 = 1;
export const importantData_2 = 2;
export default function foo () {}

การนำเข้า:

ประเภทของการส่งออก (เช่นชื่อหรือการส่งออกเริ่มต้น) มีผลกระทบต่อวิธีการบางสิ่งบางอย่างนำเข้า:

  1. สำหรับการส่งออกที่มีชื่อเราจะต้องใช้เครื่องหมายปีกกาและชื่อที่แน่นอนเป็นการประกาศ (เช่นตัวแปรฟังก์ชั่นหรือคลาส) ซึ่งถูกส่งออก
  2. สำหรับการส่งออกเริ่มต้นเราสามารถเลือกชื่อ

ไวยากรณ์:

// Module B, imports from module A which is located in the same directory

import { importantData_1 , importantData_2  } from './A';  // for our named imports

// syntax single named import: 
// import { importantData_1 } 

// for our default export (foo), the name choice is arbitrary
import ourFunction from './A';   

สิ่งที่น่าสนใจ:

  1. ใช้รายการคั่นด้วยเครื่องหมายจุลภาคภายในเครื่องหมายปีกกาที่มีชื่อที่ตรงกันของการส่งออกสำหรับการส่งออกที่มีชื่อ
  2. ใช้ชื่อที่คุณเลือกโดยไม่มีเครื่องหมายปีกกาสำหรับการส่งออกเริ่มต้น

นามแฝง:

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

import { importantData_1 as myData } from './A';

ตอนนี้เราได้นำเข้าimportantData_1 แต่ระบุเป็นแทนmyDataimportantData_1


5

โดยปกติเมื่อคุณส่งออกฟังก์ชันที่คุณต้องใช้ {}

if you have export const x 

คุณใช้ import {x} from ''

if you use export default const x 

คุณต้องใช้import X from '' ที่นี่คุณสามารถเปลี่ยน X เป็นตัวแปรอะไรก็ได้ที่คุณต้องการ


4

วงเล็บปีกกา ({}) ใช้เพื่ออิมพอร์ตการโยงที่มีชื่อและแนวคิดเบื้องหลังคือการกำหนดค่าการทำลายโครงสร้าง

การสาธิตง่ายๆว่าคำสั่งการนำเข้าทำงานกับตัวอย่างได้อย่างไรในคำตอบของฉันสำหรับคำถามที่คล้ายกันที่เราจะใช้ '{}' ในการนำเข้าจาวาสคริปต์เมื่อใด


1
คุณจะได้รับคะแนนโหวตสำหรับคำตอบสั้น ๆ ที่ดีที่สุด!
Eric Bishard

0

วงเล็บปีกกาจะใช้สำหรับการนำเข้าเฉพาะเมื่อมีการส่งออกชื่อ หากการส่งออกเป็นค่าเริ่มต้นวงเล็บปีกกาจะไม่ถูกใช้เพื่อการนำเข้า


0

สำหรับการส่งออกเริ่มต้นเราจะไม่ใช้ {} เมื่อเรานำเข้า

เช่น

player.js

export default vx;

index.js

import vx from './player';

index.js ป้อนคำอธิบายรูปภาพที่นี่

player.js ป้อนคำอธิบายรูปภาพที่นี่

หากเราต้องการนำเข้าทุกสิ่งที่เราส่งออกเราจะใช้ * ป้อนคำอธิบายรูปภาพที่นี่

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