การใช้ const อย่างเหมาะสมเพื่อกำหนดฟังก์ชันใน JavaScript


183

ฉันสนใจถ้ามีข้อ จำกัด ใด ๆ กับประเภทของค่าที่สามารถตั้งค่าได้โดยใช้constใน JavaScript - ในฟังก์ชั่นเฉพาะ ถูกต้องหรือไม่ ได้รับมันใช้งานได้ แต่มันถือว่าเป็นการปฏิบัติที่ไม่ดีไม่ว่าด้วยเหตุผลใด?

const doSomething = () => {
   ...
}

ควรกำหนดฟังก์ชั่นทั้งหมดด้วยวิธีนี้ใน ES6 หรือไม่ ดูเหมือนว่าจะไม่เป็นเช่นนี้ถ้าเป็นเช่นนั้น

ขอบคุณสำหรับความคิดเห็นใด ๆ !


ดูเหมือนว่าคุณจะถามคำถามหลายข้อ: 1) "ฉันสนใจถ้ามีข้อ จำกัด เกี่ยวกับประเภทของค่าที่สามารถตั้งค่าโดยใช้ const ใน JavaScript"หมายเลข 2) "ถูกต้องหรือไม่" ใช่. 3) "ถือว่าเป็นการปฏิบัติที่ไม่ดีไม่ว่าด้วยเหตุผลใดก็ตาม"ฉันเดาว่ามันไม่ได้อยู่นานพอที่จะพูดอะไรเกี่ยวกับเรื่องนั้น แต่ฉันไม่เห็นว่าทำไมการฝึกแบบนี้จึงควรเป็นแผ่น var doSomething = <function def>;มันไม่ได้แตกต่างกันมากจาก 4) "ควรกำหนดฟังก์ชั่นทั้งหมดด้วยวิธีนี้ใน ES6 หรือไม่" ดูเหมือนว่าจะยุ่งยากสำหรับฉัน ฉันชอบประกาศฟังก์ชั่น ทุกคนเป็นของตัวเอง
เฟลิกซ์ลิ่ง

1
วิธีที่ฉันเห็นมัน (ความเห็นไม่ใช่ความจริง) มันสมเหตุสมผลถ้าคุณไม่อนุญาตให้กำหนดฟังก์ชันใหม่ ไม่ว่าจะมีเหตุผลหรือมีประโยชน์ใช้สอย - เป็นที่ถกเถียงกัน หากคุณคิดว่ามันเหมาะกับสถานการณ์การใช้งานของคุณฉันไม่คิดว่ามีใครบางคนสามารถโต้แย้งการตัดสินใจของคุณและถือว่ามันเป็นการปฏิบัติที่ไม่ดี
Mjh

4
constผมคิดว่าคำถามคือสิ่งที่คุณต้องการที่จะประสบความสำเร็จกับ คุณต้องการป้องกันไม่ให้ตัวคุณเองเอาชนะฟังก์ชั่นนี้หรือไม่? ฉันคิดว่าคุณรู้รหัสของคุณที่จะไม่ทำเช่นนี้ คุณต้องการที่จะแสดงความตั้งใจของdoSomethingมันคือว่ามันมีฟังก์ชั่นและไม่เปลี่ยนค่าหรือไม่ ฉันคิดว่าการประกาศฟังก์ชั่นสื่อสารเจตนานี้อย่างชัดเจนเช่นกัน ดังนั้นหากคุณต้องการ "การป้องกันรันไทม์" จากการเอาชนะให้ทำมัน ไม่อย่างนั้นฉันไม่เห็นประโยชน์มากนัก แน่นอนถ้าคุณใช้เป็นหลักในการใช้งานvar foo = function() {};ผมจะใช้แทนconst var
เฟลิกซ์ลิ่ง

5
@ FelixKling "ฉันคิดว่าคุณรู้รหัสของคุณที่จะไม่ทำเช่นนี้" - นี่เป็นข้อโต้แย้งที่ไม่ดีนัก มิฉะนั้นจะไม่มีเหตุผลconstอะไรเลย
คดเคี้ยว

คำตอบ:


254

ไม่มีปัญหากับสิ่งที่คุณทำ แต่คุณต้องจำความแตกต่างระหว่างการประกาศฟังก์ชั่นและการแสดงออกของฟังก์ชั่น

การประกาศฟังก์ชั่นนั่นคือ:

function doSomething () {}

ถูกยกขึ้นไปด้านบนสุดของขอบเขต (และชอบletและconstพวกเขาจะถูกบล็อกขอบเขตเช่นกัน)

ซึ่งหมายความว่าสิ่งต่อไปนี้จะได้ผล:

doSomething() // works!
function doSomething() {}

การแสดงออกฟังก์ชั่นนั่นคือ:

[const | let | var] = function () {} (or () =>

คือการสร้างฟังก์ชั่นที่ไม่ระบุชื่อ ( function () {}) และการสร้างตัวแปรแล้วการกำหนดฟังก์ชั่นที่ไม่ระบุชื่อให้กับตัวแปรนั้น

ดังนั้นกฎทั่วไปเกี่ยวกับการยกตัวแปรภายในขอบเขต - ตัวแปรบล็อกที่มีขอบเขต ( letและconst) ไม่ยกขึ้นundefinedไปด้านบนของขอบเขตบล็อก

หมายความว่า:

if (true) {
    doSomething() // will fail
    const doSomething = function () {}
}

จะล้มเหลวเนื่องจากdoSomethingไม่ได้กำหนดไว้ (มันจะโยน ReferenceError)

หากคุณเปลี่ยนไปใช้varคุณจะได้รับการยกตัวแปร แต่จะเริ่มต้นเพื่อundefinedให้บล็อกของรหัสข้างต้นยังคงไม่ทำงาน (นี่จะเป็นการโยนTypeErrorตั้งแต่doSomethingไม่ใช่ฟังก์ชันในเวลาที่คุณเรียกใช้)

เท่าที่มาตรฐานการปฏิบัติไปคุณควรใช้เครื่องมือที่เหมาะสมสำหรับงาน

Axel Rauschmayer มีการโพสต์ที่ยอดเยี่ยมเกี่ยวกับขอบเขตและการยกรวมถึงความหมาย es6: ตัวแปรและการกำหนดขอบเขตใน ES6


7
ต้องการเพิ่มคลาส es6 ที่ใช้ const ภายในเพื่อป้องกันชื่อคลาสจากการกำหนดใหม่ภายในคลาส
user2342460

2
ความแตกต่างหนึ่งที่ลึกซึ้งระหว่างและคือถ้าคุณเรียกมันเหมือนในก็จะพิมพ์ในก็จะพิมพ์ function a(){console.log(this);} const a=_=>{console.log(this);}a.call(someVar);someVarwindow
Qian Chen

100

แม้ว่าจะใช้constเพื่อกำหนดฟังก์ชั่นที่ดูเหมือนแฮ็ค แต่มันมาพร้อมกับข้อดีที่ยอดเยี่ยมที่ทำให้มันเหนือกว่า (ในความคิดของฉัน)

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

  2. คุณสามารถใช้ไวยากรณ์ลูกศรอ้วนซึ่งสั้นกว่าและสะอาดกว่า

  3. การใช้ฟังก์ชั่นลูกศรดูแลการthisผูกพันสำหรับคุณ

ตัวอย่างด้วย function

// define a function
function add(x, y) { return x + y; }

// use it
console.log(add(1, 2)); // 3

// oops, someone mutated your function
add = function (x, y) { return x - y; };

// now this is not what you expected
console.log(add(1, 2)); // -1

ตัวอย่างเดียวกันกับ const

// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;

// use it
console.log(add(1, 2)); // 3

// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged


1
และคุณสามารถประกาศฟังก์ชั่นสองครั้งเพิ่ม (x, y) แต่คุณไม่สามารถประกาศเพิ่ม const สองครั้ง = ...
TatianaP

33
1. การเปลี่ยนไม่ได้เป็นผลประโยชน์ที่แท้จริง แต่ก็เป็นเรื่องยากสำหรับบางคนที่จะเขียนทับฟังก์ชั่น 2. ไวยากรณ์ของลูกศรไขมันจะไม่สั้นลงเว้นแต่ว่าฟังก์ชันของคุณจะเป็นนิพจน์ function f(x, y) {มี 18 ตัวอักษรconst f = (x, y) => {คือ 21 ตัวอักษรดังนั้นยาวกว่า 3 ตัว 3. การรักษาความผูกพันนี้จะเกิดขึ้นก็ต่อเมื่อฟังก์ชั่นถูกกำหนดไว้ภายในเมธอด (หรือฟังก์ชันอื่นที่มีความหมายนี้) ที่สคริปต์ระดับบนสุดมันไม่มีจุดหมาย ฉันไม่ได้บอกว่าคุณคิดผิดเพียง แต่เหตุผลที่คุณพูดถึงนั้นไม่เกี่ยวข้องกันมากนัก
Nakedible

@Nakedible ดังนั้นเหตุผลที่ถูกต้องมีอะไรบ้าง
Anish Ramaswamy

13
ข้อดีอย่างหนึ่งของไวยากรณ์ฟังก์ชั่นแบบเก่าคือในระหว่างการดีบั๊กมันมีชื่อ
user949300

3
ฉันจะใช้ linters เพื่อป้องกันไม่ให้ผูกพันประกาศฟังก์ชัน
Franklin Yu

32

เป็นเวลาสามปีแล้วที่มีคนถามคำถามนี้ แต่ฉันเพิ่งจะเจอมัน เนื่องจากคำตอบนี้อยู่ไกลจากกองโปรดให้ฉันทำซ้ำ:

ถาม:ฉันสนใจถ้ามีข้อ จำกัด เกี่ยวกับประเภทของค่าที่สามารถตั้งค่าได้โดยใช้ const ใน JavaScript - โดยเฉพาะฟังก์ชั่น ถูกต้องหรือไม่ จริงอยู่ที่มันได้ผล แต่มันก็ถือว่าเป็นการฝึกฝนที่ไม่ดีไม่ว่าด้วยเหตุผลใด?

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

ในคำตอบของ " ถือว่าเป็นการปฏิบัติที่ไม่ดีไม่ว่าด้วยเหตุผลใด ๆ หรือไม่ " ให้ฉันพูดว่า IMO ใช่หรืออย่างน้อยก็มีข้อดีในการใช้functionคำสั่ง

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

ความสับสนอย่างต่อเนื่อง: ทำไมฉันยังคงใช้งบฟังก์ชัน JavaScriptโดย medium.freecodecamp.org/Bill Sourour, ปราชญ์ JavaScript, ที่ปรึกษาและอาจารย์

ฉันขอให้ทุกคนอ่านบทความนั้นแม้ว่าคุณจะตัดสินใจแล้ว

นี่คือประเด็นหลัก:

คำสั่งฟังก์ชั่นมีข้อดีสองอย่างที่ชัดเจนเหนือ [const] การแสดงออกของฟังก์ชัน

ประโยชน์ # 1: ความชัดเจนของเจตนา

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

ข้อได้เปรียบ # 2: ลำดับของการประกาศ == ลำดับของการดำเนินการ

เป็นการดีที่ฉันต้องการประกาศรหัสของฉันมากขึ้นหรือน้อยลงตามลำดับที่ฉันคาดว่าจะได้รับการดำเนินการ

นี่คือตัวหยุดการแสดงสำหรับฉัน: ค่าใด ๆ ที่ประกาศโดยใช้คำสำคัญ const นั้นไม่สามารถเข้าถึงได้จนกว่าการประมวลผลจะถึง

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

สมองของฉันไม่ทำงานอย่างนั้น ฉันต้องการบริบทก่อนรายละเอียด

รหัสส่วนใหญ่เขียนโดยมนุษย์ ดังนั้นจึงเป็นความรู้สึกว่าคำสั่งของคนส่วนใหญ่ในการทำความเข้าใจคร่าวๆตามคำสั่งของการดำเนินการของรหัสส่วนใหญ่


1
คุณสามารถแสดงความคิดเห็นเพิ่มเติมเกี่ยวกับความชัดเจนของเจตนาได้หรือไม่? ฉันได้รับ # 2 แต่เท่าที่ฉันสามารถบอกได้ว่า # 1 เป็นเพียงการกล่าวซ้ำ (ก่อนหน้า) ของ # 2 ฉันสามารถคิดกรณีเช่นฟังก์ชั่นที่มีdefaultErrorHandlerconst ของตัวเองได้รับมอบหมายเป็นฟังก์ชั่นที่ไม่ระบุชื่อที่ฉันสามารถโทรจากตัวจัดการสัญญา สิ่งนี้จะทำให้ฉันสามารถเลือก 'แทนที่' ตัวจัดการข้อผิดพลาดเริ่มต้นนี้ภายในฟังก์ชันตามที่ฉันต้องการ บางคนแค่ต้องการส่งคืนวัตถุข้อผิดพลาดและบางคนต้องการกลับการตอบสนอง http ซึ่งเป็นระดับที่แตกต่างกันของ verbosity แต่โครงสร้างของรหัสสามารถเป็นรูปแบบที่คุ้นเคยได้
Jake T.

บางทีความคิดของฉันก็ซับซ้อนเกินไป! เพียงคลุมหัวของฉันเกี่ยวกับแนวทางปฏิบัติใหม่ ๆ บางอย่างยังไม่ได้ใช้เวลามากมายในการนำพวกเขาไปใช้ เพียงแค่พบว่าฉันชอบ.then( res.success, res.error )มากกว่าฟังก์ชั่นที่ไม่ระบุชื่อที่ฉันประกาศให้เรียกres.success(value);เท่านั้น การมี.then( ..., defaultErrorHandler)รูปแบบทั่วไปอาจเป็นสิ่งที่ดีโดยฟังก์ชัน defaultErrorHandler ที่กำหนดไว้ระดับบนสุดและอาจมีการconst defaultErrorHandler = error => { ... }ประกาศภายในขอบเขตฟังก์ชันตามที่ต้องการ
Jake T.

1
@JakeT RE "คุณสามารถแสดงความคิดเห็นเพิ่มเติมเกี่ยวกับความชัดเจนของเจตนาได้หรือไม่" ก่อนอื่นคำพูดนั้นไม่ได้ทำให้ฉัน แต่โดย freecodecamp.org/Bill Sourour ผู้เขียนบทความนั้น แต่มันก็เป็นเรื่องจริงสำหรับฉัน ถ้าฉันอ่าน "ฟังก์ชั่นพรุ่งนี้ ()" ฉันก็รู้ทันทีว่ามันคือฟังก์ชั่น แต่ถ้าฉันอ่าน "const tomorrow = () =>" ฉันจะหยุดสักครู่แล้วแยกวิเคราะห์ไวยากรณ์ในหัวของฉันเพื่อกำหนดสุดท้ายตกลงใช่มันเป็นฟังก์ชั่น
JMichaelTX

1
อีกอย่างหนึ่งถ้าฉันมีคนเขียนสคริปต์ยาว ๆ และฉันต้องการเห็นฟังก์ชั่นทั้งหมดฉันสามารถค้นหา "ฟังก์ชั่น" เพื่อค้นหาพวกมันได้อย่างรวดเร็ว หรือดียิ่งกว่านั้นฉันสามารถเขียน JS RegEx อย่างรวดเร็วเพื่อแยกฟังก์ชันทั้งหมด IMO คำสั่ง "const" เป็นเพียงข้อมูล (ไม่ใช่ฟังก์ชัน) ที่จะไม่เปลี่ยนแปลง
JMichaelTX

10

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

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

สิ่งที่คุณสามารถอนุมานเมื่อคุณอ่านconst? คุณรู้ทั้งหมดต่อไปนี้เพียงแค่อ่านconstคำสั่งประกาศและโดยไม่ต้องสแกนหาการอ้างอิงอื่น ๆ ไปยังตัวแปรนั้น:

  • ค่าถูกผูกไว้กับตัวแปรนั้น (แม้ว่าวัตถุต้นแบบจะไม่เปลี่ยนแปลงไม่ได้ลึก)
  • ไม่สามารถเข้าถึงได้นอกบล็อกที่มีบล็อกทันที
  • การเข้าถึงไม่ถูกผูกไว้ก่อนที่จะประกาศเนื่องจากกฎ Temporal Dead Zone (TDZ)

ข้อความต่อไปนี้จากบทความเถียงประโยชน์ของและlet constนอกจากนี้ยังตอบคำถามของคุณโดยตรงเกี่ยวกับข้อ จำกัด / ข้อ จำกัด ของคำหลัก:

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

จริงอยู่ที่ว่ามีกฎมากกว่าในการconstประกาศมากกว่าการvarประกาศ: block-scoped, TDZ, มอบหมายที่การประกาศ, ไม่มีการมอบหมายใหม่ ในขณะที่varคำสั่งเฉพาะการกำหนดขอบเขตสัญญาณฟังก์ชั่น อย่างไรก็ตามการนับกฎไม่ได้ให้ข้อมูลเชิงลึกมากนัก มันจะดีกว่าที่จะชั่งน้ำหนักกฎเหล่านี้ในแง่ของความซับซ้อน: กฎจะเพิ่มหรือลบความซับซ้อนหรือไม่ ในกรณีของการconstกำหนดขอบเขตบล็อกหมายถึงขอบเขตที่แคบกว่าการกำหนดขอบเขตฟังก์ชัน TDZ หมายความว่าเราไม่จำเป็นต้องสแกนขอบเขตย้อนกลับจากการประกาศเพื่อตรวจสอบการใช้งานก่อนการประกาศและกฎการมอบหมายหมายความว่าการผูกจะรักษา การอ้างอิงเดียวกัน

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

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

ที่มา: https://ponyfoo.com/articles/var-let-const

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