`ส่งออก const` เทียบกับ 'default default' ใน ES6


204

ฉันพยายามที่จะตรวจสอบว่ามีความแตกต่างใหญ่ระหว่างสองเหล่านี้นอกเหนือจากความสามารถในการนำเข้าexport defaultโดยเพียงทำ:

import myItem from 'myItem';

และการใช้export constฉันสามารถทำได้:

import { myItem } from 'myItem';

ฉันสงสัยว่ามีความแตกต่างและ / หรือใช้กรณีอื่นนอกเหนือจากนี้หรือไม่


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

4
@spmurrayzzz: FWIW การผูกการนำเข้าก็ไม่เปลี่ยนรูปแบบเหมือนconstกัน
เฟลิกซ์ลิ่ง

ขอบคุณสำหรับ @FelixKling ชี้แจงที่ไม่ทราบว่า
spmurrayzzz

@ FelixKling: จากภายนอกอย่างน้อย อาจไม่คงที่แม้ว่าการส่งออกสามารถเปลี่ยนแปลงได้
Bergi

@Bergi: ถูกต้องนั่นคือเหตุผลที่ผมบอกว่าผูกนำเข้า ;)
เฟลิกซ์แพรว

คำตอบ:


326

เป็นการส่งออกที่มีชื่อเทียบกับการส่งออกเริ่มต้น export constเป็นการส่งออกที่ระบุชื่อซึ่งส่งออกการประกาศ const หรือการประกาศ

หากต้องการเน้น: สิ่งสำคัญที่นี่คือexportคำหลักที่constใช้เพื่อประกาศการประกาศ const หรือการประกาศ exportอาจนำไปใช้กับการประกาศอื่น ๆ เช่นการประกาศคลาสหรือฟังก์ชั่น

ส่งออกเริ่มต้น ( export default)

คุณสามารถส่งออกเริ่มต้นหนึ่งไฟล์ต่อหนึ่งไฟล์ เมื่อคุณนำเข้าคุณต้องระบุชื่อและนำเข้าดังนี้:

import MyDefaultExport from "./MyFileWithADefaultExport";

คุณสามารถตั้งชื่อที่คุณชอบได้

ส่งออกที่มีชื่อ ( export)

ด้วยการส่งออกที่ระบุชื่อคุณสามารถมีการส่งออกที่กำหนดชื่อหลายรายการต่อไฟล์ จากนั้นนำเข้าการส่งออกเฉพาะที่คุณต้องการในวงเล็บปีกกา:

// ex. importing multiple exports:
import { MyClass, MyOtherClass } from "./MyClass";
// ex. giving a named import a different name by using "as":
import { MyClass2 as MyClass2Alias } from "./MyClass2";

// use MyClass, MyOtherClass, and MyClass2Alias here

หรือเป็นไปได้ที่จะใช้ค่าเริ่มต้นพร้อมกับการนำเข้าที่มีชื่อในคำสั่งเดียวกัน:

import MyDefaultExport, { MyClass, MyOtherClass} from "./MyClass";

นำเข้า Namespace

เป็นไปได้ที่จะนำเข้าทุกสิ่งจากไฟล์บนวัตถุ:

import * as MyClasses from "./MyClass";
// use MyClasses.MyClass, MyClasses.MyOtherClass and MyClasses.default here

หมายเหตุ

  • ไวยากรณ์ช่วยให้การส่งออกเริ่มต้นมีความรัดกุมขึ้นเล็กน้อยเนื่องจากกรณีการใช้งานของพวกเขาเป็นเรื่องธรรมดามากขึ้น ( ดูการอภิปรายที่นี่ )
  • การส่งออกเริ่มต้นคือการส่งออกที่มีชื่อพร้อมชื่อdefaultดังนั้นคุณจึงสามารถนำเข้าได้ด้วยการนำเข้าที่มีชื่อ:

    import { default as MyDefaultExport } from "./MyFileWithADefaultExport";

24

export defaultส่งผลกระทบต่อไวยากรณ์เมื่อนำเข้า "สิ่งของ" ที่ส่งออกเมื่ออนุญาตให้นำเข้าสิ่งใดก็ตามที่ถูกส่งออกโดยการเลือกชื่อในimportตัวเองไม่ว่าชื่อจะถูกส่งออกเมื่อใดก็ตามเพราะมันถูกระบุว่าเป็น "ค่าเริ่มต้น"

กรณีการใช้ประโยชน์ที่ฉันชอบ (และใช้งาน) จะช่วยให้การส่งออกที่ไม่ระบุชื่อฟังก์ชั่นโดยไม่ต้องชัดเจนมีการตั้งชื่อและเมื่อฟังก์ชั่นที่นำเข้าจะต้องมีการกำหนดชื่อ:


ตัวอย่าง:

ส่งออก 2 ฟังก์ชั่นหนึ่งคือdefault:

export function divide( x ){
    return x / 2;
}

// only one 'default' function may be exported and the rest (above) must be named
export default function( x ){  // <---- declared as a default function
    return x * x;
}

นำเข้าฟังก์ชั่นด้านบน การสร้างชื่อให้กับdefault:

// The default function should be the first to import (and named whatever)
import square, {divide} from './module_1.js'; // I named the default "square" 

console.log( square(2), divide(2) ); // 4, 1

เมื่อ{}ไวยากรณ์ถูกใช้เพื่อนำเข้าฟังก์ชั่น (หรือตัวแปร) หมายความว่าสิ่งใดก็ตามที่ถูกนำเข้านั้นถูกตั้งชื่อแล้วเมื่อถูกส่งออกดังนั้นผู้ใช้จะต้องนำเข้าโดยใช้ชื่อเดียวกันแน่นอนมิฉะนั้นการนำเข้าจะไม่ทำงาน


ตัวอย่างผิดพลาด:

  1. ฟังก์ชั่นเริ่มต้นจะต้องนำเข้าก่อน

    import {divide}, square from './module_1.js
  2. divide_1ไม่ได้ถูกส่งออกmodule_1.jsดังนั้นจึงไม่มีการนำเข้า

    import {divide_1} from './module_1.js
  3. squareไม่ถูกส่งออกmodule_1.jsเนื่องจาก{}บอกให้เอ็นจิ้นค้นหาการส่งออกที่ระบุชื่ออย่างชัดเจนเท่านั้น

    import {square} from './module_1.js

ไม่ได้หมายความว่ามันส่งออกสิ่งเดียว คุณสามารถมีหลายชื่อและหนึ่งค่าเริ่มต้นในโมดูลเดียวกัน เริ่มต้นก็หมายความว่าที่ - มันส่งออกเริ่มต้นถ้าคุณไม่ได้ระบุชื่อเมื่อนำเข้าเช่นแทนimport something from import { somethingNamed } from
Andris

ฉันยังได้เรียนรู้คำศัพท์ภาษาอังกฤษใหม่ที่นี่: "ผิดพลาด" +1 สำหรับสิ่งนั้น
Yuval Levy

12

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

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

export default class Foo { }

//the name 'Foo' could be anything, since it's just an
//identifier for the default export
import Foo from './Foo'

ตอนนี้ถ้าคุณปรับโครงสร้างFooคลาสของคุณให้เป็นBarและเปลี่ยนชื่อไฟล์ IDE ส่วนใหญ่จะไม่แตะนำเข้าของคุณ ดังนั้นคุณจะจบลงด้วยสิ่งนี้:

export default class Bar { }

//the name 'Foo' could be anything, since it's just an
//identifier for the default export.
import Foo from './Bar'

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

export class Foo { }

//'Foo' needs to be the class name. The import will be refactored
//in case of a rename!
import { Foo } from './Foo'

2
" 'Foo' ต้องเป็นชื่อคลาส " - ไม่! คุณสามารถทำได้อย่างง่ายดายเช่นimport { Foo as Anything } from …เดียวimport Anything from …กับการส่งออกเริ่มต้น
Bergi

การที่คุณสามารถเปลี่ยนชื่อด้วยความasจริงนั้นไม่ใช่จุดในความคิดเห็นของแหล่งนั้น ขอบคุณสำหรับ downvote; p
Philipp Sumi

1
ฉันไม่ได้ลงคะแนน แต่ฉันไม่แน่ใจว่าข้อโต้แย้งนั้นน่าเชื่อถือหรือไม่ ฉันไม่รู้ว่าฉันต้องการให้ IDE ของฉันเปลี่ยนชื่อการนำเข้าทั้งหมดเมื่อทำการเปลี่ยนโมดูลใหม่หรือไม่นั่นคือสิ่งที่ modularisation เกี่ยวกับ :-) และดูเหมือนว่าจะเป็น "ปัญหา" ของ IDE มากกว่าไม่ใช่เหตุผลในการเลือกรูปแบบการส่งออก …
Bergi

ฉันยอมรับว่าฉันใช้การส่งออกที่กำหนดชื่อเพื่อประโยชน์ของนักพัฒนา UX ที่นี่ - แต่จากนั้นคุณสามารถยืนยันได้ว่า typescript ต่อ se เป็นเรื่องเกี่ยวกับสิ่งนั้น ฉัน refactor บ่อยครั้งและเนื่องจากฉันมักจะมีหนึ่งคลาส (ในกรณีของฉัน: React Component) ต่อไฟล์ฉันต้องการให้การนำเข้าเป็นไปตามองค์ประกอบที่เปลี่ยนชื่ออย่างแน่นอนเพื่อไม่สร้างการเชื่อมต่อ แน่นอนว่าสิ่งนี้อาจจะเหมาะสมหรือไม่ขึ้นอยู่กับนักพัฒนาแต่ละคน
Philipp Sumi

ฉันพบบทความที่บอกว่าเหมือนกัน อาจเป็นตำแหน่งที่เหมาะสม: เราควรใช้export defaultสำหรับการส่งออกวัตถุหลักของโครงการโดยเฉพาะอย่างยิ่งจากแพคเกจ npm (มันแทนที่ a module.exports =) แต่ภายในโครงการควรใช้การส่งออกที่มีชื่อเท่านั้น
Paleo

7

จากเอกสาร :

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

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


0

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


0

ฉันมีปัญหาที่เบราว์เซอร์ไม่ได้ใช้ es6

ฉันได้แก้ไขด้วย:

 <script type="module" src="index.js"></script>

โมดูลประเภทบอกเบราว์เซอร์ให้ใช้ ES6

export const bla = [1,2,3];

import {bla} from './example.js';

จากนั้นมันควรจะทำงาน

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