เมื่อใดที่ฉันควรใช้ `return 'ในฟังก์ชั่นลูกศร es6


154

ฟังก์ชั่นลูกศร es6ใหม่บอกreturnเป็นนัยภายใต้สถานการณ์บางอย่าง:

นิพจน์เป็นค่าส่งคืนโดยนัยของฟังก์ชันนั้น

ฉันจำเป็นต้องใช้returnกับฟังก์ชั่นลูกศร es6 ในกรณีใดบ้าง

คำตอบ:


262

แจ็คสันได้ตอบคำถามนี้บางส่วนด้วยคำถามที่คล้ายกัน:

ส่งคืนโดยนัย แต่เฉพาะในกรณีที่ไม่มีบล็อก

  • returnซึ่งจะส่งผลในข้อผิดพลาดเมื่อมีการขยายตัวหนึ่งซับหลายเส้นและลืมโปรแกรมเมอร์ที่จะเพิ่ม
  • การส่งคืนโดยนัยมีความกำกวมทางไวยากรณ์ (name) => {id: name}ส่งคืนวัตถุ{id: name}... ใช่ไหม ไม่ถูกต้อง. มันกลับundefinedมา เครื่องมือจัดฟันเหล่านั้นเป็นบล็อกที่ชัดเจน id:เป็นฉลาก

ฉันจะเพิ่มคำจำกัดความของบล็อกนี้ :

คำสั่งบล็อก (หรือคำสั่งผสมในภาษาอื่น ๆ ) จะใช้ในการจัดกลุ่มคำสั่งเป็นศูนย์หรือมากกว่า บล็อกถูกคั่นด้วยวงเล็บปีกกาคู่

ตัวอย่าง :

// returns: undefined
// explanation: an empty block with an implicit return
((name) => {})() 

// returns: 'Hi Jess'
// explanation: no block means implicit return
((name) => 'Hi ' + name)('Jess')

// returns: undefined
// explanation: explicit return required inside block, but is missing.
((name) => {'Hi ' + name})('Jess')

// returns: 'Hi Jess'
// explanation: explicit return in block exists
((name) => {return 'Hi ' + name})('Jess') 

// returns: undefined
// explanation: a block containing a single label. No explicit return.
// more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
((name) => {id: name})('Jess') 

// returns: {id: 'Jess'}
// explanation: implicit return of expression ( ) which evaluates to an object
((name) => ({id: name}))('Jess') 

// returns: {id: 'Jess'}
// explanation: explicit return inside block returns object
((name) => {return {id: name}})('Jess') 

ฉันไม่ได้รับไวยากรณ์ .. คุณสร้างคลาสโดยใช้ littoral คลาสแล้วเรียก constructor ที่มีนัยโดยมีหนึ่งอาร์กิวเมนต์ ('Jess') หรือไม่? ฉันคิดว่าคุณจะทำสิ่งนี้ ((ชื่อ) => ({id: 'Jess'}))
Michael Dausmann

3
@MichaelDausmann มันเป็นฟังก์ชั่นลูกศรที่มีหนึ่งพารามิเตอร์โดยnameมีฟังก์ชั่นล้อมรอบอยู่ในวงเล็บและเรียกใช้ด้วยอาร์กิวเมนต์เดียว "Jess" รหัสระหว่าง=>และ)('Jess')ในแต่ละกรณีคือส่วนของฟังก์ชั่นลูกศร ลองคิดว่ามันเป็นรูปแบบย่อของ Expression Function ที่ถูกเรียกใช้ในทันทีของแบบฟอร์ม(function (name) { return { id: name } })('Jess')
Russ Cam

มีประโยชน์มาก indded! ช่วยแก้ไขปัญหาสปอตใน Promises.all ที่แมปไอเท็มที่มีฟังก์ชั่นลูกศรและคุณสามารถสังเกตได้ว่าคุณได้รับอาเรย์ที่ไม่ได้กำหนดหรือไม่หากไม่มีการส่งคืนค่าสำหรับการแมปผ่านอาเรย์ด้วยฟังก์ชันลูกศร
jay shah

ข้อเสียของการทำระบบส่งคืนโดยนัยสำหรับฟังก์ชั่นลูกศรคืออะไร เช่นเดียวกับ coffeescript ทำ ... (แต่ฉันไม่ชอบ coffeescript)
Augustin Riedinger

4
เพื่อความชัดเจนดูเหมือนว่าเพราะ parser JS ไม่ทราบว่าจะคาดหวังการแสดงออก (เช่นการแสดงออกที่มีวัตถุตัวอักษร{}) หรือบล็อกมันจะถือว่าสมมติว่า{ }บล็อก ซึ่งหมายความว่าว่าเมื่อมันเห็นid: nameก็คิดว่าid:คือการแสดงออกการสร้างป้ายชื่อ (คุณลักษณะที่มากผิดปกติที่ใช้ JS ที่เกี่ยวข้องกับการควบคุมการไหลและใช้:) และจากนั้นnameต่อไปนี้id:เป็นเพียงคำสั่งที่แยกต่างหากที่มีเพียงตัวแปรname(& ไม่ทำอะไรเลย)
iono

18

ฉันเข้าใจกฎง่ายๆนี้ ...

สำหรับฟังก์ชั่นที่มีการแปลงอย่างมีประสิทธิภาพ (หนึ่งบรรทัดจัดการกับข้อโต้แย้ง) การส่งคืนจะเป็นนัย

ผู้สมัครคือ:

// square-root 
value => Math.sqrt(value)

// sum
(a,b) => a+b

สำหรับการดำเนินการอื่น ๆ (มากกว่าหนึ่ง liners ที่ต้องใช้บล็อกการส่งคืนจะต้องชัดเจน


11

มีอีกกรณีที่นี่

เมื่อเขียนคอมโพเนนต์ที่ใช้งานได้ใน React คุณสามารถใช้วงเล็บเพื่อตัด JSX ที่ส่งคืนโดยปริยาย

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);

4
คุณสามารถใช้วงเล็บได้ซึ่งไม่เกี่ยวข้องกับ JSX หรือ React
Emile Bergeron

4

นี่เป็นอีกกรณีหนึ่งที่ทำให้ฉันมีปัญหา

// the "tricky" way
const wrap = (foo) => (bar) => {
  if (foo === 'foo') return foo + ' ' + bar;
  return 'nofoo ' + bar;
}

ที่นี่เรากำหนดฟังก์ชั่นกลับฟังก์ชั่นที่ไม่ระบุชื่อบิต "หากิน" ก็คือร่างกายฟังก์ชั่นสำหรับฟังก์ชั่นด้านนอก (ส่วนที่เริ่มต้นด้วย (บาร์) => ... ) สายตาดูเหมือนว่า "บล็อก" เนื่องจากมันไม่ได้ผลตอบแทนโดยปริยายเตะเข้า

นี่คือวิธีการตัดคำสั่ง:

// use wrap() to create a function withfoo()
const withfoo = wrap('foo');
// returns: foo bar
console.log(withfoo('bar'));

// use wrap() to create a function withoutfoo()
const withoutfoo = wrap('bar');
// returns: nofoo bar
console.log(withoutfoo('bar'));

วิธีที่ฉันนำสิ่งเหล่านี้ออกมาเพื่อให้แน่ใจว่าฉันเข้าใจว่ามันคือ "แยก" ฟังก์ชั่นออก

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

// the explicit return way
const wrap = (foo) => {
  return (bar) => {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  }
}

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

// the "no arrow functions" way
const wrap = function(foo) {
  return function(bar) {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  };
};

ในที่สุดสำหรับคนอื่น ๆ ที่อาจต้องอ่านรหัสของฉันและในอนาคตฉันฉันคิดว่าฉันอยากไปรุ่นลูกศรที่ไม่สามารถเข้าใจได้อย่างเห็นได้ชัดตั้งแต่แรกเห็นมากกว่าลูกศรที่ใช้เวลาพอสมควร คิด (และในกรณีของฉันทดลอง) เพื่อ grok


3

ฟังก์ชั่นลูกศรช่วยให้คุณได้รับผลตอบแทนโดยนัย: มีการส่งคืนค่าโดยไม่ต้องใช้returnคำหลัก

มันทำงานเมื่อมีคำสั่งออนไลน์ในร่างกายฟังก์ชั่น:

const myFunction = () => 'test'

console.log(myFunction()) //'test'

อีกตัวอย่างหนึ่งการคืนค่าวัตถุ (อย่าลืมวงเล็บปีกกาในวงเล็บเพื่อหลีกเลี่ยงการถูกพิจารณาว่าเป็นตัวยึดฟังก์ชันตัวยึด):

const myFunction = () => ({value: 'test'})

console.log(myFunction()) //{value: 'test'}


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