ใช้วงเล็บกับไวยากรณ์การนำเข้าจาวาสคริปต์


115

ฉันเจอไลบรารี javascript ที่ใช้ไวยากรณ์ต่อไปนี้เพื่อนำเข้าไลบรารี:

import React, { Component, PropTypes } from 'react';

อะไรคือความแตกต่างระหว่างวิธีการข้างต้นและวิธีต่อไปนี้?

import React, Component, PropTypes from 'react';

4
คำตอบอยู่ในเอกสาร
adeneo

4
สมาชิกที่จะนำเข้าจากโมดูลจะอยู่ใน
ปีกกา


1
ฮ้า หากเรากำจัดทุกครั้งที่สามารถตอบคำถาม SO ด้วย "RTFM" ได้แม้แต่ Jon Skeet ก็อาจมีตัวเลขไม่ถึงหกตัว ; ^)
ruffin

คำตอบ:


174
import React, { Component, PropTypes } from 'react';

สิ่งนี้กล่าวว่า:

นำเข้าการส่งออกเริ่มต้นจาก'react'ภายใต้ชื่อReactและนำเข้าการส่งออกที่มีชื่อComponentและPropTypesภายใต้ชื่อเดียวกัน

ซึ่งรวมไวยากรณ์ทั่วไปสองแบบที่คุณอาจเคยเห็น

import React from 'react';
import { Component, PropTypes } from 'react';

รายการแรกถูกใช้เพื่ออิมพอร์ตและตั้งชื่อการเอ็กซ์พอร์ตดีฟอลต์ตัวที่สองเพื่ออิมพอร์ตการเอ็กซ์พอร์ตที่ระบุชื่อ

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

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

import name from "module-name";

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

อีกวิธีหนึ่งในการอธิบายสิ่งนี้คือการสังเกตว่าการนำเข้าข้างต้นนั้นเหมือนกันทุกประการ

import { default as name } from "module-name";

และตัวอย่างของ OP นั้นเหมือนกับ

import { default as React, Component, PropTypes } from 'react';

เอกสาร MDN ได้แสดงตัวอย่างต่อไป

import MyModule, {foo, bar} from "my-module.js";

และอ้างว่ามันหมายถึง

นำเข้าเนื้อหาของโมดูลทั้งหมดโดยบางส่วนมีการตั้งชื่ออย่างชัดเจน สิ่งนี้แทรกmyModule(sic) fooและbarเข้าไปในขอบเขตปัจจุบัน โปรดทราบว่าfooและmyModule.fooจะเหมือนกันเช่นเดียวกับbarและmyModule.bar

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

นำเข้าการส่งออกโมดูลเริ่มต้นและการส่งออกบางรายการที่มีชื่อชัดเจน แทรกนี้MyModule, fooและbarเข้าไปในขอบเขตปัจจุบัน ชื่อการส่งออกfooและbarมีไม่สามารถเข้าถึงได้ผ่านMyModuleซึ่งเป็นค่าเริ่มต้นการส่งออกไม่ได้ร่มบางครอบคลุมการส่งออกทั้งหมด

(การส่งออกโมดูลเริ่มต้นคือค่าที่ส่งออกด้วยexport defaultไวยากรณ์ซึ่งอาจเป็นได้export {foo as default}เช่นกัน)

ผู้เขียนเอกสาร MDN อาจสับสนกับแบบฟอร์มต่อไปนี้:

import * as MyModule from 'my-module';

สิ่งนี้จะนำเข้าการส่งออกทั้งหมดจากmy-moduleและทำให้สามารถเข้าถึงได้ภายใต้ชื่อเช่นMyModule.name. การส่งออกเริ่มต้นยังสามารถเข้าถึงได้เป็นเนื่องจากการส่งออกเริ่มต้นคือจริงๆไม่มีอะไรมากไปกว่าที่อื่นส่งออกชื่อที่มีชื่อMyModule.default defaultในไวยากรณ์นี้ไม่มีวิธีใดที่จะอิมพอร์ตเฉพาะส่วนย่อยของการเอ็กซ์พอร์ตที่ระบุชื่อแม้ว่าจะสามารถอิมพอร์ตการเอ็กซ์พอร์ตเริ่มต้นได้หากมีร่วมกับเอ็กซ์พอร์ตที่ระบุชื่อทั้งหมดด้วย

import myModuleDefault, * as myModule from 'my-module';

1
Babel ยอมรับfrom '/path/to/my-module.js'แม้ว่าฉันจะใช้เป็นการส่วนตัวfrom '/path/to/my-module'ก็ตาม
royhowie

5
ด้วยคำอธิบายโดยละเอียดดังกล่าวคุณควรเพิ่มวิธีการส่งออกเพื่อที่จะนำเข้าเช่นนั้น
Caio Iglesias

37
import React, { Component, PropTypes } from 'react'

สิ่งนี้จะดึง{ Component, PropTypes }สมาชิกที่ส่งออกจาก'react'โมดูลและมอบหมายให้ComponentและPropTypesตามลำดับ Reactจะเท่ากับการdefaultส่งออกของโมดูล

ตามที่ระบุไว้ใน torazaburo ด้านล่างนี้จะเหมือนกับ

import { default as React, Component, PropTypes } from 'react'

ซึ่งเป็นชวเลขสำหรับ

import { default as React, Component as Component, PropTypes as PropTypes} from 'react'

นี่คืออีกตัวอย่างหนึ่ง ( ลิงก์ไปยังส่วนสำคัญ ):

// myModule.js
export let a = true
export let b = 42
export let c = 'hello, world!'
// `d` is not exported alone
let d = 'some property only available from default'

// this uses the new object literal notation in es6
// {myVar} expands to { myVar : myVar }, provided myVar exists
// e.g., let test = 22; let o = {test}; `o` is then equal to { test : 22 }
export default { a, b, d }

// example1.js
import something from 'myModule'
console.log(something)
// this yields (note how `c` is not here):
/*
  {
    a : true,
    b : 42,
    d : 'some property only available from default'
  }
*/

// example2.js
import something, { c } from 'myModule'
console.log(something)  // same as above; the `default` export
console.log(c)          // c === 'hello, world!'

// example3.js
import { a, b, d, default as something } from 'myModule'
console.log(a)            // a === true
console.log(b)            // b === 42
console.log(d)            // d === undefined (we didn't export it individually)
console.log(something.d)  // something.d === 'some property...'

ฉันทดสอบตัวอย่างที่สองด้วย babel:

import test, test3, test2 from './app/lib/queries.js'
console.log(test, test3, test2)

และมีข้อผิดพลาดทางไวยากรณ์

~/code/repo/tutoring $ babel-node test.js
/Users/royhowie/.node/lib/node_modules/babel/node_modules/babel-core/lib/babel/transformation/file/index.js:601
      throw err;
            ^
SyntaxError: /Users/royhowie/code/repo/tutoring/test.js: Unexpected token (1:13)
> 1 | import test, test3, test2 from './app/lib/queries.js'
    |              ^
  2 | 
  3 | console.log(test, test3, test2)
  4 | 

สำหรับการอ้างอิงคุณสามารถอ่านimportเอกสารใหม่จาก MDN อย่างไรก็ตามเห็นได้ชัดว่าจำเป็นต้องมีการตรวจสอบทางเทคนิค โพสต์บล็อกของ Dr. Axel Rauschmayerเป็นข้อมูลอ้างอิงที่ดีกว่าสำหรับตอนนี้


1
สิ่งนี้จะดึงคุณสมบัติ {Component, PropTypes} จากการเอ็กซ์พอร์ตในโมดูล "react" และกำหนดให้กับ React สิ่งนี้ไม่ถูกต้อง กำหนดการส่งออกเริ่มต้นReactและการส่งออกที่มีชื่อComponentและPropTypesตัวแปรที่มีชื่อเดียวกัน ขออภัยเอกสาร MDN ไม่ถูกต้องเนื่องจากคุณจะพบว่าคุณได้ลองใช้หรือไม่ ดู2ality.com/2014/09/es6-modules-final.html นอกจากนี้ไวยากรณ์การนำเข้าไม่มีส่วนเกี่ยวข้องกับการมอบหมายการทำลายโครงสร้าง

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

1
@torazaburo ฉันเขียนคำตอบใหม่ให้ถูกต้องมากขึ้น
royhowie

@royhowie ขอบคุณมากสำหรับตัวอย่างนี้ !! ช่วยประหยัดเวลาอีกหนึ่งชั่วโมงในการท่องไปรอบ ๆ โดยไม่คิด ... ฉันมีคำถามเดียว ในexample3.jsทำไมมันพิมพ์undefinedสำหรับconsole.log(d)? เนื่องจากคุณทำexport default { a, b, d }เช่นนั้นคุณจึงส่งออกในรูปแบบmyModule.js.
CapturedTree

2
@ 1290 ในmyModule.jsทราบว่าa, bและcถูกส่งออกเป็นรายบุคคล ซึ่งหมายความว่าไฟล์อื่นสามารถนำเข้าโดยตรงด้วยimport { a } from 'myModule'. ในทางกลับกันdสามารถใช้งานได้ผ่านการส่งออกเริ่มต้นเท่านั้นดังนั้นโมดูลอื่นจึงสามารถเข้าถึงได้สองวิธี: import thisObjectContainsDefault from 'myModule'และเข้าถึงผ่านthisObjectContainsDefault.dOR import { default as wrapperObject }และwrapperObject.d. example3.jsประโยชน์ของวิธีที่สองคือการที่คุณยังสามารถคว้ารายการที่ถูกส่งออกเป็นรายบุคคลที่สามารถเห็นได้ใน
royhowie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.