การคืนค่าʻundefined` หรือ `null` จากฟังก์ชัน javascript จะดีกว่าไหม


98

ฉันมีฟังก์ชั่นที่ฉันเขียนซึ่งโดยทั่วไปมีลักษณะดังนี้:

function getNextCard(searchTerms) {
  // Setup Some Variables

  // Do a bunch of logic to pick the next card based on termed passed through what I'll call here as 'searchTerms' all of this logic is omitted because it's not important for my question.
  // ...

  // If we find a next card to give, than give it
  if (nextCardFound)
    return nextCardFound;

  // Otherwise - I'm returning undefined
  return undefined;
}

คำถาม: กลับ "null" ที่นี่จะดีกว่าไหม

ฉันสามารถผ่านอะไรก็ได้ที่ต้องการกลับมา - เห็นได้ชัดว่า ... ฉันไม่แน่ใจว่าอะไรคือสิ่งที่ดีที่สุดที่จะใช้

รหัสที่เรียกใช้ฟังก์ชันนี้รู้วิธีจัดการกับ undefined (จริงๆแล้วจะไม่เกิดขึ้นจริง ๆ เว้นแต่จะมีบางอย่างผิดพลาดอย่างน่ากลัว)

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


เอกสารประกอบ:

Mozilla Docsไม่ได้ตอบคำถามของฉัน ... google ไม่ได้: \

คำถาม SO นี้ - กว้างเกินไปสำหรับสิ่งที่ฉันพยายามหาที่นี่


1
SO คำถามนี้ไม่ตอบ?
warkentien2

8
nullในความคิดของผลตอบแทน ปล่อยundefinedให้ JavaScript เอง อย่างไรก็ตามไม่มี "ดีกว่า" ดังนั้นนี่จึงเป็นเรื่องของความคิดเห็น
Felix Kling

@ warkentien2 ขอบคุณสิ่งนี้มีประโยชน์ - แต่ฉันยังไม่ชัดเจนว่าการประชุมที่นี่คืออะไรสำหรับการกลับมาจากฟังก์ชัน getter
Jeremy Iglehart

1
ฉันอ่านnullว่า "ไม่มีคุณค่าที่เหมาะสมสำหรับสิ่งที่คุณขอ" และundefinedในฐานะ "ฉันไม่สามารถหาสิ่งที่คุณต้องการได้"
Marty

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

คำตอบ:


37

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

ตัวอย่างเช่น:

  • [[ต้นแบบ]]

    วัตถุธรรมดามีสล็อตภายใน [[Prototype]] ซึ่งกำหนดว่าวัตถุอื่น ๆ จะสืบทอดมาจากวัตถุใด แน่นอนว่าต้องมีวิธีที่จะบอกว่าวัตถุนั้นไม่ได้รับมรดกจากสิ่งอื่นใด ในกรณีนี้ "ไม่มีวัตถุดังกล่าว" nullเป็นตัวแทนโดยใช้

  • Object.getOwnPropertyDescriptor

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

  • document.getElementById

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

ดังนั้นเพียงแค่เลือกสิ่งที่คุณต้องการหรือคิดว่าเหมาะสมกับกรณีของคุณ


3
หลังจากอ่านสิ่งนี้ฉันตัดสินใจที่จะแนะนำvoid 0เทคนิคสำหรับผู้ชมในอนาคตของคำตอบนี้ ฉันยังได้เพิ่มรหัสเพื่อพยายามทำให้ประเด็นของคุณชัดเจนยิ่งขึ้น ขอบคุณสำหรับคำตอบ!
Jeremy Iglehart

114

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

จากข้อมูลจำเพาะ ECMAScript2015

4.3.10 ค่าที่ไม่ได้กำหนด

ค่าดั้งเดิมใช้เมื่อไม่ได้กำหนดค่าตัวแปร

4.3.12 ค่า null

ค่าดั้งเดิมที่แสดงถึงการไม่มีค่าวัตถุใด ๆ โดยเจตนา

http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-undefined-type

อ่านเพิ่มเติม:

เมื่อใดที่เป็นโมฆะหรือไม่ได้กำหนดถูกใช้ใน JavaScript


1
ใช่ค่าที่ไม่ได้กำหนดคือค่าที่ใช้เมื่อไม่ได้กำหนดค่าตัวแปร เหตุใดสิ่งนั้นจึงบ่งบอกว่าคุณไม่ควรส่งคืนสิ่งที่ไม่ได้กำหนดไว้ในฟังก์ชัน
Oriol

1
@Oriol ในความคิดของฉันเนื่องจากฟังก์ชัน void ส่งคืนไม่ได้กำหนดนั่นคือค่าที่สงวนไว้สำหรับฟังก์ชันประเภทนั้นดังนั้นเมื่อจัดการกับค่าที่ส่งคืนของฟังก์ชัน null จะบอกฉันว่ามันตัดสินใจที่จะคืนค่า null ในขณะที่ไม่ได้กำหนดบอกฉัน ตัดสินใจที่จะกลับไปโดยไม่ได้กำหนดหรือตัดสินใจที่จะไม่คืนอะไร แต่ฉันไม่รู้แน่ชัดว่า นอกจากนี้หากฉันกำลังทำอยู่var x=someFunc();ฉันตั้งใจกำหนดค่า xa และค่อนข้างจะไม่ผ่านการทดสอบใด ๆ ที่ระบุว่าไม่ได้กำหนดค่า (หรืออาจไม่ได้) Just imho
ChiliNUT

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

1
ฉันไม่อ่านแบบนั้น ฉันอ่านว่า: หากคุณกำหนดตัวแปร แต่ไม่ได้กำหนดค่าเริ่มต้นตัวแปรนั้นจะมีค่าเริ่มต้นเป็น undefined แทน โปรแกรมเมอร์ควรใช้ค่า Null เพื่อระบุว่าตัวแปรว่างเปล่าโดยเจตนา โปรแกรมเมอร์ไม่ควรกำหนด IMHO ที่ไม่ได้กำหนดให้กับตัวแปรปล่อยให้มันขึ้นอยู่กับเครื่องมือ js เพื่อใช้งาน คำว่าค่า "อ็อบเจกต์" ทำให้เข้าใจผิดเนื่องจากใน JS แม้แต่สิ่งดั้งเดิมก็ยังทำตัวเหมือนออบเจ็กต์ส่วนใหญ่เนื่องมาจากการทำ
กล่องอัตโนมัติ

1
ใช่มันสมเหตุสมผลแล้ว เพื่อความเป็นธรรมฉันไม่รังเกียจที่จะใช้อีกอันหนึ่ง (แม้ว่าฉันจะคุ้นเคยมากกว่าnull) ตราบใดที่คุณยึดติดกับค่าหนึ่ง แต่การมี 2 ค่าเพื่อบ่งชี้ว่าไม่มีค่า (ไม่ว่าจะเป็น "ประเภทใด" ก็ตาม) มักจะสับสน
Sergio Rosas

39

ฉันจะให้ความเห็นส่วนตัวของฉันในการเลือกระหว่างทั้งสอง

คำถามง่ายๆของฉันคือ: ค่าสามารถกำหนดอินพุต / สถานะ / บริบทให้กับบางสิ่งได้หรือไม่?

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

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

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


1
แหวนนี้เป็นจริงสำหรับฉัน ฟังก์ชั่นที่บริสุทธิ์ของ IMO ควรกลับมาnullในขณะที่ฟังก์ชันที่มีผลข้างเคียงควรกลับมาundefinedเมื่อคิดเหมือนโปรแกรมเมอร์ที่ใช้งานได้
Jake

4

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

ลองพิจารณาตัวอย่างนี้

function getSomething() {
     // .. do something
     return undefined;
}

function doSomething() {
     // .. I'm not gonna return anything.
}

var a = getSomething();
var b = doSomething();

ผลตัวอย่างข้างต้นซึ่งเป็นa === b undefinedความแตกต่างคือคุณบันทึก 1 การดำเนินการคำสั่ง


@Oriol ฉันหมายถึงundefinedไม่จำเป็นต้องได้รับมอบหมาย undefinedทั้งหมดประกาศตัวแปรโดยไม่ต้องค่าที่มีอยู่แล้ว
choz

@choz & @Oriol - ตามที่กล่าวไว้ก่อนหน้านี้โดย @chiliNUT "โปรดทราบว่าฟังก์ชันที่ไม่มีค่าส่งคืนที่ระบุโดยปริยายจะส่งคืนไม่ได้กำหนด" - นี่เป็นความจริงเนื่องจาก(function(){ /* code */ })()ส่งคืนค่าว่างในคอนโซล
Jeremy Iglehart

@JeremyIglehart รหัสนั้นจริงๆแล้วไม่ส่งคืนอะไรเลย และอื่น ๆ มันให้undefinedบนคอนโซล Chrome และ Firefox ของฉัน
choz

ตกลงฉันไม่เข้าใจประเด็นของคุณ ใช่หากคุณไม่ส่งคืนสิ่งใด ๆ อย่างชัดเจน undefined จะถูกส่งกลับโดยปริยาย แต่ทำไมเรื่องนั้น?
Oriol

1
@Oriol ฉันคิดว่าสิ่งที่ @choz พยายามจะพูด (ตามที่คนอื่น ๆ กล่าวถึงในคำถามนี้) ว่าถ้าฉันต้องการกลับundefinedถ้าอย่างอื่นไม่กลับมาก่อนหน้านี้ - ฉันไม่จำเป็นต้องทำเพราะพฤติกรรมเริ่มต้นของฟังก์ชันถ้า คุณไม่ส่งคืนสิ่งใดเลยคือการส่งคืนโดยไม่ได้กำหนด - พวกเขาบอกว่าสิ่งนี้ไม่จำเป็น เพิ่มเติม ... ฉันชอบสิ่งที่คุณพูดเกี่ยวกับฟังก์ชัน getter ในตัวที่คืนค่า null กรุณาโพสต์คำตอบของคุณเกี่ยวกับผลกระทบนั้นและฉันจะยอมรับมัน
Jeremy Iglehart

3

ขึ้นอยู่กับว่าคุณต้องทำอะไรกับค่าที่ส่งคืน

typeof null ส่งคืนวัตถุ วัตถุนั้นมีค่าไม่ได้กำหนด

typeof undefined ส่งกลับไม่ได้กำหนด


โดยส่วนตัวแล้วฉันมักจะใช้ null
แดน

4
"วัตถุนั้นมีค่าไม่ได้กำหนด"ไม่ใช่ไม่ใช่และไม่ใช่วัตถุ แต่เป็นค่า Null typeofไม่จำเป็นต้องส่งคืนประเภทข้อมูลที่แท้จริงของค่า แต่มีแผนที่ที่จับคู่ประเภทข้อมูลกับป้ายกำกับและส่งคืนป้ายกำกับที่เกี่ยวข้อง
Felix Kling

อย่าวางใจtypeofแม้ว่าชื่อจะไม่ได้บอกประเภทของค่า
Oriol

2

นี่คือตัวอย่างที่undefinedสมเหตุสมผลมากกว่าnull:

ฉันใช้ฟังก์ชัน wrapper เพื่อJSON.parseแปลงข้อยกเว้นเป็นundefined:

// parses s as JSON if possible and returns undefined otherwise
// return undefined iff s is not a string or not parseable as JSON; undefined is not a valid JSON value https://stackoverflow.com/a/14946821/524504
function JSON_parse_or_undefined(s) {
    if ("string" !== typeof s) return undefined

    try {
        const p = JSON.parse(s)
        return p
    } catch (x){}

    return undefined
}

โปรดทราบว่าnullใช้ได้ใน JSON ในขณะที่undefinedไม่ใช่


ฉันเห็นว่าคุณกำลังทำอะไรอยู่ที่นั่นและฉันไม่สามารถพูดได้ว่าคุณผิดเพราะในแง่หนึ่งฉันคิดว่าคุณสามารถทำสิ่งนี้ที่นี่ได้และมันจะดี ฉันมีรูปแบบอื่นที่ฉันใช้ในการดำเนินการนี้ซึ่งฉันชอบมากกว่าเพราะฉันทำขั้นตอน "การตรวจสอบ" หลังจากนั้น ฉันรู้สึกว่านี่เป็นการตรวจสอบความถูกต้องผสมกับการคืนค่า นี่คือสิ่งที่ฉันทำ: let getStringOrJSON = value => { try { value = JSON.parse(value); } catch(e) { return value; } return value; };. ตอนนี้ฉันแน่ใจว่าผลตอบแทนทั้งสองสามารถจัดการได้แตกต่างกันและอาจไม่ชนะการแข่งขันกอล์ฟ JS มันได้ผล.
Jeremy Iglehart

1

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

ฉันมักจะใช้ค่าว่างในการพัฒนาแม้ว่าฉันจะคิดว่าเป็นเรื่องที่เป็นส่วนตัว

ฉันใช้ส่วนใหญ่เพราะ:

  1. ตัวแปรที่ไม่ได้กำหนดอาจถูกเขียนทับในเบราว์เซอร์เก่าดังนั้นการส่งคืนมันจึงซับซ้อนกว่าเล็กน้อย ปัญหาเดียวกันนี้บังคับให้คุณใช้typeof var === 'undefined'เมื่อได้รับผลลัพธ์ของฟังก์ชันลิงค์

  2. ภาษาอื่น ๆ มักจะใช้ null กันอย่างแพร่หลายส่วนมากไม่มีการกำหนด (เช่น php) นั่นทำให้ฉันมีความสอดคล้องกันเมื่อสลับระหว่างภาษาอย่างรวดเร็ว


1

ฉันคิดว่ามันเป็นที่ถกเถียงกันมากว่าจะใช้อะไร ฉันชอบรหัสที่มีความหมายตามความหมายมากที่สุดดังนั้นฉันคิดว่าundefinedเหมาะสมในกรณีนี้

ฉันคิดว่าการnullมอบหมายงานมีความหมายว่า ซึ่งตรงข้ามกับundefinedความหมาย "สิ่งนี้ไม่มีเลย"

ตามที่คำตอบก่อนหน้านี้ชี้ให้เห็นว่าการส่งคืนundefinedมีปัญหาและขึ้นอยู่กับคุณว่าจะรบกวนคุณ มันจะไม่รบกวนฉัน


2
แต่document.getElementById('iDoNotExist')ผลตอบแทนnullแม้ว่าความหมายจะใกล้เคียงกับ "สิ่งนี้ไม่มีเลย" ถ้าวิธีมาตรฐานทำได้ทำไมไม่ OP?
Oriol

@Oriol ฉันชอบเหตุผลของคุณมากที่สุด กรุณาโพสต์คำตอบของผลกระทบนี้และฉันจะยอมรับมัน (ฉันอาจเพิ่มการแก้ไขเล็กน้อยหากจำเป็น)
Jeremy Iglehart

ใช่ @Oriol นี่คือเหตุผลว่าทำไมฉันถึงสนุกกับการโต้วาทีแม้แต่ในเว็บไซต์ Q / A เป็นเรื่องดีมากที่จะได้รับตัวอย่างตอบโต้ และคุณได้จัดหาสิ่งที่ดี
Ryan Laboucane

1

ฉันขอแย้งว่าในกรณีนี้nullควรส่งคืน

หากคุณพิจารณาคำถามจากมุมมองทางวิทยาศาสตร์คอมพิวเตอร์เชิงทฤษฎีจะใช้undefinedเพื่อระบุการไม่ยุติ / ไม่สามารถคำนวณได้ (เช่นตัวยึดตำแหน่งสำหรับจุดที่ไม่ได้กำหนดxของฟังก์ชันบางส่วน fซึ่งมักเขียนf(x) = ⊥ )

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

ที่ถูกกล่าวว่าเป็นค่าพิเศษการส่งสัญญาณการเลิกจ้างโดยไม่ต้องผลที่มีความหมาย (คือ "มีบัตรไม่มีฉันสามารถกลับสำหรับการป้อนข้อมูลนี้") เป็นสิ่งจำเป็นและสำหรับฉันก็คือไม่ได้nullundefined


หมายเหตุ:

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

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

ในท้ายที่สุดความชอบส่วนตัวของฉันจะไม่กลับมาในundefinedที่ที่ฉันสามารถกลับมาได้nullและฉันก็ขอเถียงว่านี่เป็นรูปแบบการเข้ารหัสที่ดีกว่า (เพราะสิ่งอื่น ๆx !== nullนั้นสั้นกว่าtypeof x !== 'undefined')


-2

ความคิดเห็นส่วนตัวของฉันตามประสบการณ์ของฉันคืออย่าใช้ undefined และเป็นโมฆะหากคุณไม่ต้องการที่จะทำให้รหัสของคุณผิดพลาด อย่างน้อยก็เลี่ยงเป็นการส่วนตัว มีฟังก์ชั่นมากมายใน Javascript ที่คืนค่าไม่ได้กำหนดและเราต้องใช้มัน แต่เมื่อคุณออกแบบโค้ดของคุณอย่าใช้มัน สิ่งสำคัญคือต้องคืนบางสิ่ง"false"อย่างน้อยที่สุดเสมอ หากคุณมีอาร์เรย์เช่นและคุณจับคู่มัน มันไม่ได้เป็นสิ่งที่ดีที่จะกลับหรือเพียงแค่[undefined, undefined.....] undefinedจะดีกว่าถ้าคุณเก็บประเภทของอาร์เรย์เดิมไว้ ตัวอย่าง:

 const mapper:Map <string[],boolean[]>  
['i', 'dont', 'use', 'null or undefined'] -> [false, true, false, true, false]
or ['', dont, '', '', use] 
or al the stuff above and then filter(v => v)
that will keep all undefined and null out

นั่นคือความคิด ฉันพยายามตลอดเวลาเพื่อหลีกเลี่ยงมัน เนื่องจากnullหรือundefinedสามารถทำให้รหัสของคุณผิดพลาดได้อย่างง่ายดาย

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