การตรวจจับคุณสมบัติของวัตถุที่ไม่ได้กำหนด


คำตอบ:


2680

วิธีปกติในการตรวจสอบว่ามูลค่าของทรัพย์สินเป็นค่าพิเศษundefinedหรือไม่คือ:

if(o.myProperty === undefined) {
  alert("myProperty value is the special value `undefined`");
}

ในการตรวจสอบว่าวัตถุไม่มีคุณสมบัติเช่นนั้นจริง ๆ หรือไม่และจะส่งกลับเป็นundefinedค่าเริ่มต้นเมื่อคุณลองและเข้าถึง:

if(!o.hasOwnProperty('myProperty')) {
  alert("myProperty does not exist");
}

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

if(typeof myVariable === 'undefined') {
  alert('myVariable is either the special value `undefined`, or it has not been declared');
}

ในเวอร์ชันของ JavaScript ก่อน ECMAScript 5 คุณสมบัติชื่อ "undefined" บนวัตถุโกลบอลสามารถเขียนได้ดังนั้นการตรวจสอบอย่างง่ายfoo === undefinedอาจทำงานโดยไม่คาดคิดหากมีการกำหนดใหม่โดยไม่ตั้งใจ ใน JavaScript ที่ทันสมัยคุณสมบัติเป็นแบบอ่านอย่างเดียว

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

หากคุณกังวลเกี่ยวกับกรณีขอบ (ไม่น่า) นี้คุณสามารถใช้ตัวดำเนินการ voidเพื่อรับundefinedค่าพิเศษเอง:

if(myVariable === void 0) {
  alert("myVariable is the special value `undefined`");
}

9
หากบางสิ่งบางอย่างเป็นโมฆะมันถูกกำหนดไว้ (เป็นโมฆะ) แต่คุณสามารถเชื่อมการตรวจสอบด้วย รายละเอียดที่น่ารำคาญของโค้ดด้านบนคือคุณไม่สามารถกำหนดฟังก์ชั่นเพื่อตรวจสอบได้ดีคุณสามารถกำหนดฟังก์ชั่น ... แต่ลองใช้มัน
neu-rah

5
@ neu-rah ทำไมคุณไม่สามารถเขียนฟังก์ชั่นได้? ทำไมจะไม่ชอบงานนี้ ดูเหมือนว่าจะทำงานให้ฉัน มีกรณีที่ฉันไม่ได้พิจารณาหรือไม่? jsfiddle.net/djH9N/6
Zack

7
@ แซคการทดสอบของคุณสำหรับ isNullorUndefined ไม่ได้พิจารณากรณีที่คุณเรียก isNullOrUndefined (f) และ f ไม่ได้ประกาศ (เช่นที่ไม่มีการประกาศ "var f")
pnkfelix

109
ตอนนี้ Blah โหวตหลายพัน นี่เป็นวิธีที่แย่ที่สุดที่จะทำได้ ฉันหวังว่าผู้คนโดยเห็นความคิดเห็นนี้และตัดสินใจที่จะตรวจสอบ ... อะแฮ่ม ... คำตอบอื่น ๆ
Ry-

17
คุณสามารถใช้obj !== undefinedตอนนี้ undefinedเคยเป็นที่ไม่แน่นอนเช่นundefined = 1234สิ่งที่จะทำให้เกิดผลลัพธ์ที่น่าสนใจ แต่หลังจาก Ecmascript 5 มันไม่สามารถเขียนได้อีกต่อไปดังนั้นเราจึงสามารถใช้เวอร์ชันที่ง่ายกว่านี้ได้ codereadability.com/how-to-check-for-undefined-in-javascript
Bruno Buccolo

899

ฉันเชื่อว่ามีคำตอบที่ไม่ถูกต้องสำหรับหัวข้อนี้ ขัดกับความเชื่อทั่วไป "undefined" ไม่ใช่คำหลักใน JavaScript และในความเป็นจริงสามารถมีค่าที่กำหนดให้

รหัสที่ถูกต้อง

วิธีที่แข็งแกร่งที่สุดในการทำแบบทดสอบนี้คือ:

if (typeof myVar === "undefined")

นี่จะส่งคืนผลลัพธ์ที่ถูกต้องเสมอและยังจัดการกับสถานการณ์ที่myVarไม่ได้ประกาศ

รหัสเสื่อม ไม่ได้ใช้.

var undefined = false;  // Shockingly, this is completely legal!
if (myVar === undefined) {
    alert("You have been misled. Run away!");
}

นอกจากนี้myVar === undefinedจะเพิ่มข้อผิดพลาดในสถานการณ์ที่ myVar ไม่ได้ประกาศ


133
+1 สำหรับการสังเกตว่า myVar === ไม่ได้กำหนดจะทำให้เกิดข้อผิดพลาดหากไม่ได้ประกาศ myVar
Enrique

73
ฉันพบว่าเหตุผลแรกที่ให้ไว้ที่นี่คือไม่ใช้=== undefinedความสับสน ใช่คุณสามารถมอบหมายให้undefinedแต่ไม่มีเหตุผลอันสมควรที่จะทำเช่นนั้นและเป็นที่คาดเดาได้ว่าการทำเช่นนั้นอาจทำให้รหัสของคุณพัง ใน C คุณสามารถทำได้#define true falseและใน Python คุณสามารถกำหนดให้กับTrueและFalseแต่ผู้คนไม่รู้สึกว่าจำเป็นต้องออกแบบรหัสของพวกเขาในภาษาเหล่านั้นในลักษณะเพื่อป้องกันความเป็นไปได้ที่พวกเขาจะก่อวินาศกรรมสภาพแวดล้อมของพวกเขาเอง . ทำไมความเป็นไปได้ของการมอบหมายให้undefinedพิจารณาอย่างคุ้มค่าที่นี่
Mark Amery

19
นอกจากความคิดเห็นของ Marks แล้วฉันไม่ได้รับสิ่งนี้: "myVar === undefined จะทำให้เกิดข้อผิดพลาดในสถานการณ์ที่ไม่ได้ประกาศ myVar" - ทำไมสิ่งนี้ถึงไม่ดี? เหตุใดฉันจึงไม่ต้องการมีข้อผิดพลาดหากฉันอ้างถึงตัวแปรที่ไม่ได้ประกาศ
eis

5
จำไว้เสมอว่าคุณสามารถทำได้void 0เพื่อรับคุณค่าที่undefinedชี้ไป if (myVar === void 0)ดังนั้นคุณสามารถทำได้ 0ไม่ได้เป็นพิเศษคุณอย่างแท้จริงสามารถใส่การแสดงออกใด ๆ
Claudiu

28
ในเบราว์เซอร์ที่ทันสมัย (FF4 + IE9 + Chrome ที่ไม่รู้จัก) undefinedก็ไปไม่ได้ที่จะปรับเปลี่ยน MDN: ไม่ได้กำหนด
247702

228

แม้จะมีการแนะนำอย่างฉุนเฉียวโดยคำตอบอื่น ๆ อีกมากมายที่นี่เป็นทางเลือกที่ดีtypeof ไม่ควรใช้สำหรับการตรวจสอบว่าตัวแปรมีค่าundefinedหรือไม่เพราะทำหน้าที่เป็นการตรวจสอบค่ารวมundefinedและตัวแปรนั้นมีอยู่หรือไม่ ในส่วนใหญ่ของกรณีคุณรู้ว่าเมื่อตัวแปรที่มีอยู่และก็จะแนะนำที่มีศักยภาพสำหรับความล้มเหลวเงียบถ้าคุณพิมพ์ผิดในชื่อตัวแปรหรือในตัวอักษรสตริงtypeof'undefined'

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

ดังนั้นหากคุณกำลังตรวจจับคุณสมบัติ²ซึ่งมีความไม่แน่นอนว่าชื่อที่กำหนดจะอยู่ในขอบเขต (เช่นการตรวจสอบtypeof module !== 'undefined'ขั้นตอนในรหัสเฉพาะสำหรับสภาพแวดล้อม CommonJS) typeofเป็นตัวเลือกที่อันตรายเมื่อใช้กับตัวแปรและตัวเลือกที่ถูกต้องคือ เพื่อเปรียบเทียบค่าโดยตรง:

var foo = …;

if (foo === undefined) {
    
}

ความเข้าใจผิดที่พบบ่อยเกี่ยวกับสิ่งนี้รวมถึง:

  • การอ่านตัวแปร“ uninitialized” ( var foo) หรือพารามิเตอร์ ( function bar(foo) { … }เรียกว่าbar()) จะล้มเหลว สิ่งนี้ไม่จริง - ตัวแปรที่ไม่มีการกำหนดค่าเริ่มต้นอย่างชัดเจนและพารามิเตอร์ที่ไม่ได้รับค่าจะกลายเป็นเสมอundefinedและอยู่ในขอบเขตเสมอ

  • ที่undefinedสามารถเขียนทับได้ ยังมีอะไรอีกมากมายสำหรับเรื่องนี้ undefinedไม่ใช่คำหลักใน JavaScript มันเป็นคุณสมบัติของออบเจ็กต์ทั่วโลกแทนค่าที่ไม่ได้กำหนด อย่างไรก็ตามเนื่องจาก ES5 คุณสมบัตินี้อ่านได้อย่างเดียวและไม่สามารถกำหนดค่าได้ ไม่มีเบราว์เซอร์ที่ทันสมัยจะอนุญาตให้undefinedมีการเปลี่ยนแปลงคุณสมบัติและ ณ วันที่ 2017 กรณีนี้เป็นเวลานาน การขาดโหมดเข้มงวดไม่ส่งผลกระทบต่อundefinedพฤติกรรมของมันเช่นกัน - มันแค่สร้างข้อความเหมือนundefined = 5ไม่ทำอะไรเลยแทนที่จะโยน แม้ว่าจะไม่ใช่คำหลัก แต่คุณสามารถประกาศตัวแปรด้วยชื่อundefinedและตัวแปรเหล่านั้นสามารถเปลี่ยนแปลงได้ทำให้รูปแบบที่พบบ่อยครั้งนี้:

    (function (undefined) {
        // …
    })()

    เพิ่มเติมundefinedอันตรายกว่าการใช้ทั่วโลก หากคุณต้องรองรับ ES3 ให้แทนที่undefinedด้วยvoid 0- อย่าหันไปtypeofใช้ ( voidเป็นโอเปอเรเตอร์ unary ที่ประเมินเป็นค่าไม่ได้กำหนดสำหรับตัวถูกดำเนินการใด ๆ )

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

นี้:

if (typeof foo.bar === 'undefined') {
    
}

เทียบเท่ากับสิ่งนี้เสมอ ³:

if (foo.bar === undefined) {
    
}

และคำนึงถึงคำแนะนำข้างต้นเพื่อหลีกเลี่ยงความสับสนของผู้อ่านว่าทำไมคุณถึงใช้typeofเพราะเหมาะสมที่สุดที่จะใช้===เพื่อตรวจสอบความเท่าเทียมกันเพราะมันสามารถ refactored การตรวจสอบค่าของตัวแปรในภายหลังและเพราะมันเป็นธรรมดา รูปลักษณ์ที่ดีกว่าที่คุณควรใช้=== undefined ³ที่นี่เช่นกัน

สิ่งอื่นที่ควรพิจารณาเมื่อพูดถึงคุณสมบัติของวัตถุคือคุณต้องการตรวจสอบundefinedจริงหรือไม่ ชื่อคุณสมบัติที่กำหนดสามารถหายไปบนวัตถุ (สร้างมูลค่าundefinedเมื่ออ่าน) นำเสนอบนวัตถุเองด้วยค่าที่undefinedมีอยู่บนต้นแบบของวัตถุที่มีค่าundefinedหรืออยู่ในอย่างใดอย่างหนึ่งที่มีundefinedค่าที่ไม่ใช่ 'key' in objจะบอกคุณว่ามีกุญแจอยู่ที่ใดที่หนึ่งบนโซ่ต้นแบบของวัตถุหรือไม่และObject.prototype.hasOwnProperty.call(obj, 'key')จะบอกคุณว่ามันอยู่บนวัตถุโดยตรงหรือไม่ ฉันจะไม่ลงรายละเอียดในคำตอบนี้เกี่ยวกับต้นแบบและการใช้วัตถุเป็นแผนที่แบบสตริง - สตริงเพราะส่วนใหญ่มีจุดประสงค์เพื่อตอบโต้คำแนะนำที่ไม่ดีทั้งหมดในคำตอบอื่น ๆ โดยไม่คำนึงถึงการตีความที่เป็นไปได้ของคำถามต้นฉบับ อ่านต่อไปต้นแบบวัตถุบน MDNมากขึ้น!

choice ตัวเลือกที่ผิดปกติของชื่อตัวแปรตัวอย่าง? นี่เป็นโค้ดที่ตายจริงจากส่วนขยาย NoScript สำหรับ Firefox
²ไม่คิดว่าการไม่รู้ว่าอะไรอยู่ในขอบเขตก็โอเคโดยทั่วไปแล้ว ช่องโหว่ของโบนัสที่เกิดจากการละเมิดขอบเขตแบบไดนามิก: โครงการศูนย์ 1225 Zero
อีกครั้งโดยสมมติว่ามีสภาพแวดล้อม ES5 + และที่undefinedอ้างถึงundefinedทรัพย์สินของวัตถุระดับโลก แทนvoid 0อย่างอื่น


@BenjaminGruenbaum จริง แต่เข้าใจผิดอย่างสมบูรณ์ บริบทที่ไม่ใช่ค่าเริ่มต้นใด ๆ สามารถกำหนดของตัวเองundefinedซ่อนบริบทเริ่มต้น ซึ่งเพื่อการปฏิบัติส่วนใหญ่มีผลเช่นเดียวกับการเขียนทับมัน
blgt

23
@ blgt นั่นคือหวาดระแวงและไม่เกี่ยวข้องกับสิ่งใดในทางปฏิบัติ ทุกบริบทสามารถลบล้าง console.log, กำหนดวิธีแบบ Array อีกครั้งและสามารถแทนที่ Function.prototype.call` hooking และแก้ไขทุกครั้งที่คุณเรียกใช้ฟังก์ชันใน JavaScript การป้องกันสิ่งนี้เป็นสิ่งที่หวาดระแวงและค่อนข้างโง่ เช่นเดียวกับฉัน (และ minitech) กล่าวว่าคุณสามารถใช้void 0เพื่อเปรียบเทียบกับไม่ได้กำหนด แต่อีกครั้ง - ที่โง่และ overkill
Benjamin Gruenbaum

19
ฉันหวังว่าฉันจะมีมากกว่าหนึ่ง upvote ให้ นี่คือคำตอบที่ถูกต้องที่สุด ฉันอยากหยุดดูจริงๆtypeof something === "undefined") โค้ดจริงๆ
Simon Baumgardt-Wellander

@BenjaminGruenbaum สำหรับโปรแกรมเมอร์ที่ขี้เกียจvoid 0คือ (หนึ่งครั้ง) ทั้งสั้นลงและปลอดภัยกว่า! นั่นเป็นชัยชนะในหนังสือของฉัน
wizzwizz4

4
นี่ควรเป็นคำตอบที่ยอมรับได้จริง ๆ มันเป็นที่สุดอย่างละเอียดและทันสมัย
Patrick Michaelsen

161

ใน JavaScript มีnullและมีไม่ได้กำหนด พวกเขามีความหมายต่างกัน

  • ไม่ได้กำหนดหมายความว่าค่าตัวแปรไม่ได้ถูกกำหนดไว้ ไม่ทราบว่าค่าคืออะไร
  • nullหมายความว่าค่าตัวแปรถูกกำหนดและตั้งค่าเป็น null (ไม่มีค่า)

Marijn Haverbeke กล่าวในหนังสือออนไลน์ฟรี " Eloquent JavaScript " ของเขา (เน้นที่เหมือง):

นอกจากนี้ยังมีค่าที่คล้ายกันเป็นโมฆะซึ่งมีความหมายว่า 'ค่านี้ถูกกำหนด แต่ไม่มีค่า' ความแตกต่างในความหมายระหว่าง undefined และ null นั้นส่วนใหญ่เป็นเรื่องทางวิชาการและมักจะไม่ค่อยน่าสนใจ ในโปรแกรมภาคปฏิบัติมักจะต้องตรวจสอบว่าบางสิ่งบางอย่าง 'มีค่า' ในกรณีเหล่านี้นิพจน์บางอย่าง == ไม่ได้ถูกกำหนดอาจถูกนำมาใช้เพราะแม้ว่าพวกเขาจะไม่เหมือนกันทุกประการค่า null == undefined จะให้ผลเป็นจริง

ดังนั้นฉันเดาวิธีที่ดีที่สุดในการตรวจสอบว่ามีบางสิ่งที่ไม่ได้กำหนดจะเป็น:

if (something == undefined)

หวังว่านี่จะช่วยได้!

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

var person = {
    name: "John",
    age: 28,
    sex: "male"
};

alert(person.name); // "John"
alert(person.fakeVariable); // undefined

42
ถ้า (บางสิ่ง == ไม่ได้กำหนด) จะเขียนได้ดีกว่าราวกับว่า (บางสิ่ง === ไม่ได้กำหนด)
Sebastian Rittau

59
ควรชี้ให้เห็นว่าสิ่งนี้ไม่ปลอดภัยอย่างสมบูรณ์ undefinedเป็นเพียงตัวแปรที่ผู้ใช้สามารถกำหนดใหม่ได้: การเขียนundefined = 'a';จะทำให้รหัสของคุณไม่ทำในสิ่งที่คุณคิด การใช้typeofดีกว่าและใช้งานได้กับตัวแปร (ไม่ใช่แค่คุณสมบัติ) ที่ยังไม่ได้ประกาศ
Gabe Moothart

7
หากสิ่งที่เป็นตัวแปรทั่วโลกที่ไม่ได้กำหนด (บางสิ่ง == ไม่ได้กำหนด) จะแสดงข้อผิดพลาดของจาวาสคริปต์
Morgan Cheng

8
ปัญหานี้คือว่าถ้า var a = null ดังนั้น == ไม่ได้กำหนดประเมินเป็นจริงแม้ว่าจะมีการกำหนดอย่างแน่นอนที่สุด
แอนดรู

6
การแปลความหมายของ "ฝีปาก Javascript" ความคิดเห็นนี้ย้อนหลัง หากคุณเพียงแค่ต้องการตรวจสอบไม่ได้กำหนดรหัสที่แนะนำจะไม่ทำงาน (มันจะตรวจจับเงื่อนไขที่กำหนดไว้ แต่ยังไม่มีการกำหนดค่าใด ๆ [ienull]) ค่า null รหัสที่แนะนำ "if (something == undefined) ... " ตรวจสอบทั้ง undefined และ null (ไม่ได้ตั้งค่า) นั่นคือมันถูกตีความว่าเป็น "if ((บางสิ่งไม่ได้กำหนด) หรือ ... สิ่งที่ผู้เขียนไม่ว่าจะเป็นที่มักจะสิ่งที่คุณจริงๆต้องการที่จะตรวจสอบทั้งที่ไม่ได้กำหนดและ null
Chuck Kollars

125

สิ่งนี้หมายความว่า: "คุณสมบัติวัตถุที่ไม่ได้กำหนด" ?

จริงๆแล้วมันอาจหมายถึงสองสิ่งที่แตกต่างกันมาก! ประการแรกมันอาจหมายถึงทรัพย์สินที่ไม่เคยมีการกำหนดไว้ในวัตถุและสองก็สามารถหมายถึงทรัพย์สินที่มีค่าไม่ได้กำหนด ลองดูรหัสนี้:

var o = { a: undefined }

คือo.aไม่ได้กำหนด? ใช่ ค่าของมันคือไม่ได้กำหนด คือo.bไม่ได้กำหนด? แน่นอน! ไม่มีคุณสมบัติ 'b' เลย! ตกลงดูตอนนี้วิธีการทำงานที่แตกต่างกันในทั้งสองสถานการณ์:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

เราสามารถเห็นได้อย่างชัดเจนtypeof obj.prop == 'undefined'และobj.prop === undefinedเท่าเทียมกันและพวกเขาไม่แยกแยะสถานการณ์ที่แตกต่างเหล่านั้น และ'prop' in objสามารถตรวจจับสถานการณ์เมื่อทรัพย์สินไม่ได้ถูกกำหนดเลยและไม่ใส่ใจกับมูลค่าทรัพย์สินซึ่งอาจไม่ได้กำหนด

แล้วจะทำอย่างไรดี?

1) คุณต้องการทราบว่าคุณสมบัติไม่ได้ถูกกำหนดโดยความหมายแรกหรือที่สอง (สถานการณ์ทั่วไป)

obj.prop === undefined // IMHO, see "final fight" below

2) คุณต้องการที่จะรู้ว่าวัตถุมีคุณสมบัติบางอย่างและไม่สนใจคุณค่าของมัน

'prop' in obj

หมายเหตุ:

  • คุณไม่สามารถตรวจสอบวัตถุและคุณสมบัติของวัตถุในเวลาเดียวกัน ตัวอย่างเช่นสิ่งนี้x.a === undefinedหรือสิ่งนี้typeof x.a == 'undefined'จะเพิ่มขึ้นReferenceError: x is not definedหากไม่ได้กำหนด x
  • ตัวแปรundefinedเป็นตัวแปรทั่วโลก (จริง ๆ แล้วมันอยู่window.undefinedในเบราว์เซอร์) มันได้รับการสนับสนุนตั้งแต่ ECMAScript ฉบับที่ 1 และตั้งแต่ ECMAScript 5 มันจะอ่านเท่านั้น ดังนั้นในเบราว์เซอร์ที่ทันสมัยไม่สามารถนิยามใหม่เป็นจริงได้เนื่องจากผู้เขียนหลายคนชอบที่จะทำให้เราตกใจ แต่นี่ก็ยังเป็นจริงสำหรับเบราว์เซอร์รุ่นเก่า

การต่อสู้ครั้งสุดท้าย: obj.prop === undefinedvstypeof obj.prop == 'undefined'

ข้อดีของobj.prop === undefined:

  • มันสั้นกว่าเล็กน้อยและดูดีกว่า
  • เอ็นจิ้น JavaScript จะให้ข้อผิดพลาดแก่คุณหากคุณสะกดผิด undefined

ข้อเสียของobj.prop === undefined:

  • undefined สามารถแทนที่ได้ในเบราว์เซอร์เก่า

ข้อดีของtypeof obj.prop == 'undefined':

  • เป็นสากลจริงๆ! มันทำงานได้ในเบราว์เซอร์ทั้งเก่าและใหม่

ข้อเสียของtypeof obj.prop == 'undefined':

  • 'undefned'( สะกดผิด ) ที่นี่เป็นเพียงค่าคงที่สตริงดังนั้นเครื่องมือ JavaScript ไม่สามารถช่วยคุณได้หากคุณสะกดผิดเหมือนที่ฉันเพิ่งทำ

อัปเดต (สำหรับ JavaScript ฝั่งเซิร์ฟเวอร์):

Node.js รองรับตัวแปรโกลบอลundefinedในรูปแบบglobal.undefined(สามารถใช้งานได้โดยไม่ต้องใส่คำนำหน้า 'global') ฉันไม่รู้เกี่ยวกับการใช้งานอื่น ๆ ของ JavaScript ฝั่งเซิร์ฟเวอร์


@Bergi ขอบคุณสำหรับความคิดเห็นของคุณ ฉันแก้ไขคำตอบของฉันแล้ว ในการป้องกันของฉันฉันสามารถพูดได้ว่าในปัจจุบัน ( ณ v.0.10.18) เอกสาร Node.js อย่างเป็นทางการกล่าวว่าไม่มีอะไรเกี่ยวกับการเป็นสมาชิกของundefined globalนอกจากนี้ยังมีค่าconsole.log(global);มิได้for (var key in global) { ... }ไม่แสดงไม่ได้กำหนดเป็นสมาชิกคนหนึ่งของโลก แต่ทดสอบเหมือน'undefined' in globalแสดงตรงข้าม
Konstantin Smolyanin

4
มันไม่จำเป็นต้องมีเอกสารพิเศษตั้งแต่มันใน ECMAScript ข้อมูลจำเพาะซึ่งยังบอกว่า[[Enumerable]]เป็นเท็จ :-)
Bergi

5
เกี่ยวกับการนี้สามารถหลีกเลี่ยงได้โดยการเขียนเป็นMinuses of typeof obj.prop == 'undefined' typeof obj.prop == typeof undefinedสิ่งนี้ยังให้ความสมมาตรที่ดีมาก
hlovdal

3
@hlovdal: obj.prop === undefinedนั่นไม่มีจุดหมายโดยสิ้นเชิงเมื่อเทียบกับ
Ry-

1
เมื่อเราตอบคำถามพาดหัวตรวจจับคุณสมบัติที่ไม่ได้กำหนด“ไม่จริงสำหรับคำถาม (ต่างกันและง่ายกว่ามาก) ในประโยคแรก („ ตรวจสอบว่าไม่ได้กำหนด ... ”) คุณตอบif ('foo' in o) …คำตอบของคุณคือ คำตอบแรกที่ถูกต้องที่นี่ ค่อนข้างทุกคนอื่นเพียงแค่ตอบประโยคนั้น
Frank Nocke

70

ปัญหาเดือดลงไปสามกรณี:

  1. undefinedวัตถุที่มีคุณสมบัติและความคุ้มค่าของมันไม่ได้
  2. undefinedวัตถุที่มีคุณสมบัติและความคุ้มค่าของมันคือ
  3. วัตถุไม่มีคุณสมบัติ

สิ่งนี้บอกสิ่งที่ฉันพิจารณาว่าสำคัญ:

มีความแตกต่างระหว่างสมาชิกที่ไม่ได้กำหนดและสมาชิกที่กำหนดด้วยค่าที่ไม่ได้กำหนด

แต่โชคtypeof obj.fooไม่ดีที่ไม่บอกเราว่ามีสามกรณีที่เรามี อย่างไรก็ตามเราสามารถรวมสิ่งนี้กับ"foo" in objเพื่อแยกความแตกต่างของเคส

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

มันน่าสังเกตว่าการทดสอบเหล่านี้เหมือนกันสำหรับnullรายการด้วย

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

ฉันยืนยันว่าในบางกรณีมันสมเหตุสมผลมากกว่า (และชัดเจนกว่า) เพื่อตรวจสอบว่ามีทรัพย์สินนั้นหรือไม่มากกว่าการตรวจสอบว่าไม่ได้กำหนดไว้หรือไม่และในกรณีเดียวที่การตรวจสอบนี้จะแตกต่างกันคือกรณีที่ 2 รายการจริงในวัตถุที่มีค่าไม่ได้กำหนด

ตัวอย่างเช่นฉันเพิ่งได้รับการเปลี่ยนรหัสเป็นจำนวนมากซึ่งมีการตรวจสอบจำนวนมากว่าวัตถุนั้นมีคุณสมบัติที่กำหนดหรือไม่

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

ซึ่งชัดเจนเมื่อเขียนโดยไม่ตรวจสอบเพื่อไม่ได้กำหนด

if( "x" in blob ) { fn(blob.x); }

แต่ดังที่ได้กล่าวมาสิ่งเหล่านี้ไม่เหมือนกันทุกประการ (แต่ดีเกินพอสำหรับความต้องการของฉัน)


10
สวัสดีไมเคิล คำแนะนำที่ดีและฉันคิดว่ามันทำให้ทุกอย่างสะอาดขึ้น หนึ่ง gotcha ที่ฉันพบ แต่เมื่อใช้! ผู้ประกอบการที่มี "ใน" คุณต้องพูดif (!("x" in blob)) {}ด้วยวงเล็บในเพราะเพราะ! ผู้ประกอบการมีความสำคัญมากกว่า 'ใน' หวังว่าจะช่วยใครซักคน
Simon East

ขออภัย Michael แต่สิ่งนี้ไม่ถูกต้องหรือทำให้เข้าใจผิดอย่างน้อยในคำถามเดิม 'in' ไม่ใช่วิธีที่เพียงพอในการทดสอบว่าคุณสมบัติของวัตถุนั้นมีประเภทไม่ได้กำหนดไว้ เพื่อพิสูจน์โปรดดูซอนี้: jsfiddle.net/CsLKJ/4
tex

2
ส่วนรหัสทั้งสองนั้นทำสิ่งที่แตกต่าง! พิจารณาและวัตถุที่กำหนดโดยa = {b: undefined}; แล้วtypeof a.b === typeof a.c === 'undefined'แต่และ'b' in a !('c' in a)
mgol

3
+1 OP ไม่ได้ทำให้ชัดเจนว่ามีคุณสมบัติอยู่และมีค่าไม่ได้กำหนดหรือไม่ว่าจะเป็นคุณสมบัติที่ไม่ได้กำหนด (เช่นไม่มีอยู่)
RobG

ฉันขอแนะนำให้เปลี่ยนจุด (2. ) ในตารางแรกของคุณเป็น{ x : undefined }หรืออย่างน้อยก็เพิ่มมันเป็นทางเลือกอื่นเพื่อ (2. ) ในตาราง - ฉันต้องคิดสักครู่เพื่อให้ตระหนักถึงจุดนั้น (2. ) ประเมินว่าundefinedถึงแม้ว่า คุณพูดถึงมันในภายหลัง)
mucaho

46
if ( typeof( something ) == "undefined") 

สิ่งนี้ใช้ได้สำหรับฉันในขณะที่คนอื่นไม่ได้


47
parens ที่ไม่จำเป็นตั้งแต่ typeof เป็นผู้ดำเนินการ
aehlke

12
แต่พวกเขาทำให้ชัดเจนว่ากำลังตรวจสอบอะไรอยู่ typeof (something == "undefined")มิฉะนั้นมันอาจจะอ่านเป็น
Abhi Beckert

หากคุณต้องการวงเล็บคุณควรเรียนรู้ลำดับความสำคัญของโอเปอเรเตอร์ใน JS: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Ian

11
วงเล็บมีประโยชน์อย่างแม่นยำเพราะคุณไม่จำเป็นต้องเรียนรู้การมาก่อนของผู้ให้บริการใน JS และคุณไม่จำเป็นต้องคาดเดาว่าโปรแกรมเมอร์บำรุงรักษาในอนาคตจะต้องเรียนรู้การมาก่อนของผู้ให้บริการใน JS
DaveWalley

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

42

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

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient

จุดยอดเยี่ยมของ Eric มีประสิทธิภาพการทำงานจากการตรวจสอบประเภทด้วยหรือไม่
Simon East

5
@Simon: ค่อนข้างตรงกันข้าม - ใครจะคาดหวังว่าประสิทธิภาพจะได้รับผลกระทบเล็กน้อยจากการหลีกเลี่ยงการบีบบังคับในกรณี '===' การทดสอบที่รวดเร็วและสกปรกได้แสดง '===' เร็วกว่า '==' 5% ภายใต้ FF5.0.1
Antony Hatchkins

5
การทดสอบอย่างละเอียดมากขึ้นแสดงให้เห็นว่าภายใต้ FF, IE และ Chrome '==' เร็วกว่าหรือน้อยกว่า '===' (5-10%) และ Opera ไม่ได้สร้างความแตกต่างเลย: jsperf.com/triple- equals-vs-
two

3
การใช้==ยังคงต้องมีการตรวจสอบอย่างน้อยประเภท - ล่ามไม่สามารถเปรียบเทียบตัวถูกดำเนินการทั้งสองได้โดยไม่ทราบประเภทของพวกเขาก่อน
Alnitak

7
==เป็นตัวละครตัวหนึ่งที่น้อยกว่า===:)
svidgen

25

การข้ามคำตอบจากคำถามที่เกี่ยวข้องจะตรวจสอบ "undefined" ใน JavaScript ได้อย่างไร

someObject.<whatever>โดยเฉพาะกับคำถามนี้ให้ดูกรณีทดสอบด้วย


บางสถานการณ์แสดงภาพประกอบของคำตอบที่หลากหลาย: http://jsfiddle.net/drzaus/UVjM4/

(โปรดทราบว่าการใช้varสำหรับinการทดสอบสร้างความแตกต่างเมื่ออยู่ใน wrapper ที่กำหนดขอบเขต)

รหัสสำหรับการอ้างอิง:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

และผลลัพธ์:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

21

ถ้าคุณทำ

if (myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

มันจะล้มเหลวเมื่อmyvarไม่มีตัวแปรเนื่องจากไม่ได้กำหนด myvar ดังนั้นสคริปต์จึงขาดและการทดสอบไม่มีผล

เนื่องจากวัตถุหน้าต่างมีขอบเขตส่วนกลาง (วัตถุเริ่มต้น) นอกฟังก์ชั่นการประกาศจะถูก 'แนบ' กับวัตถุหน้าต่าง

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

var myvar = 'test';

ตัวแปรส่วนกลางmyvarเหมือนกับwindow.myvarหรือwindow ['myvar']

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

if(window.myvar == undefined )
{ 
    alert('var does not exists or is not initialized');
}

คำถามหากตัวแปรมีอยู่จริงไม่สำคัญว่าเป็นค่าที่ไม่ถูกต้อง มิฉะนั้นจะเป็นการโง่ที่จะเริ่มต้นตัวแปรด้วย undefined และควรใช้ค่า false เพื่อเริ่มต้น เมื่อคุณรู้ว่าตัวแปรทั้งหมดที่คุณประกาศถูกเตรียมใช้งานด้วยเท็จคุณสามารถตรวจสอบประเภทของมันหรือพึ่งพา!window.myvarเพื่อตรวจสอบว่ามันมีค่าที่เหมาะสม / ถูกต้อง ดังนั้นแม้ในขณะที่ตัวแปรไม่ได้กำหนดไว้แล้ว!window.myvarเหมือนกันสำหรับmyvar = undefinedหรือหรือmyvar = falsemyvar = 0

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

if( !window.myvar || typeof window.myvar != 'string' )
{
    alert('var does not exists or is not type of string');
}

เมื่อเงื่อนไขแรกและเรียบง่ายเป็นจริงล่ามจะข้ามการทดสอบถัดไป

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

(y)


19

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

if (obj && obj.prop) {
  // Do something;
}

หาก obj หรือ obj.prop ไม่ได้กำหนดเป็นโมฆะหรือ "เท็จ" คำสั่ง if จะไม่ดำเนินการบล็อกรหัส นี่คือมักจะพฤติกรรมที่ต้องการในงบป้องกันรหัสมากที่สุด (ใน JavaScript)


2
หากคุณต้องการทราบว่าทำไมจึงทำงานได้: จาวาสคริปต์: ตัวดำเนินการเชิงตรรกะและความจริง / เท็จ
mb21

หากคุณต้องการกำหนดคุณสมบัติให้กับตัวแปรถ้ามันถูกกำหนดไม่ใช่ null และไม่เป็นเท็จใช้ค่าเริ่มต้นบางอย่างคุณสามารถใช้: var x = obj && obj.prop || 'default';
Stijn de Witt

ฉันเชื่อว่าคำถามสำหรับการตรวจสอบกับไม่ได้กำหนดอย่างชัดเจน เงื่อนไขของคุณตรวจสอบกับค่าเท็จทั้งหมดของ JS
NikoKyriakid

15

ในบทความExploring the Abyss of Null และ Undefined ใน JavaScriptฉันอ่านเฟรมเวิร์กอย่างUnderscore.jsใช้ฟังก์ชั่นนี้:

function isUndefined(obj){
    return obj === void 0;
}

3
void 0เป็นเพียงวิธีสั้น ๆ ในการเขียนundefined(เนื่องจากเป็นสิ่งที่เป็นโมฆะตามด้วยนิพจน์ใด ๆ ที่ส่งคืน) จึงช่วยประหยัด 3 charcters มันสามารถทำได้เช่นvar a; return obj === a;กัน แต่นั่นก็เป็นตัวละครอีกตัวหนึ่ง :-)
RobG

2
voidเป็นคำสงวนในขณะที่undefinedไม่ได้กล่าวคือในขณะที่undefinedมีค่าเท่ากับvoid 0โดยเริ่มต้นที่คุณสามารถกำหนดค่าให้เช่นundefined undefined = 1234
Brian M. Hunt

isUndefined(obj): 16 ตัวอักษร obj === void 0: 14 ตัวอักษร 'กล่าวว่า
Stijn de Witt

14

ทุกอย่างไม่ได้ถูกกำหนดใน JavaScript คือไม่ได้กำหนดไม่สำคัญว่าจะเป็นคุณสมบัติภายในObject / Arrayหรือเป็นเพียงตัวแปรอย่างง่าย ...

JavaScript typeofช่วยให้ตรวจจับตัวแปรที่ไม่ได้กำหนดได้ง่าย

เพียงตรวจสอบว่าtypeof whatever === 'undefined'มันจะส่งคืนบูลีนหรือไม่

นั่นคือวิธีที่ฟังก์ชันที่มีชื่อเสียงisUndefined()ใน AngularJs v.1x ถูกเขียน:

function isUndefined(value) {return typeof value === 'undefined';} 

ดังนั้นตามที่คุณเห็นฟังก์ชั่นได้รับค่าถ้าค่าที่กำหนดไว้ก็จะกลับมิฉะนั้นค่าที่ไม่ได้กำหนดผลตอบแทนfalsetrue

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

var stackoverflow = {};
stackoverflow.javascipt = 'javascript';
var today;
var self = this;
var num = 8;
var list = [1, 2, 3, 4, 5];
var y = null;

และเราตรวจสอบพวกเขาตามด้านล่างคุณสามารถเห็นผลลัพธ์ต่อหน้าพวกเขาเป็นความคิดเห็น:

isUndefined(stackoverflow); //false
isUndefined(stackoverflow.javascipt); //false
isUndefined(today); //true
isUndefined(self); //false
isUndefined(num); //false
isUndefined(list); //false
isUndefined(y); //false
isUndefined(stackoverflow.java); //true
isUndefined(stackoverflow.php); //true
isUndefined(stackoverflow && stackoverflow.css); //true

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

อีกสิ่งหนึ่งสำหรับการตรวจสอบคุณสมบัติบนวัตถุในแอปพลิเคชันจริงซึ่งคุณไม่แน่ใจว่ามีวัตถุอยู่หรือไม่ให้ตรวจสอบว่าวัตถุนั้นมีอยู่ก่อนหรือไม่

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

isUndefined(x.css);
VM808:2 Uncaught ReferenceError: x is not defined(…)

ง่ายมากที่คุณสามารถสรุปคำสั่ง if ด้านล่าง:

if(typeof x !== 'undefined') {
  //do something
}

ซึ่งยังเท่ากับ isDefined ใน Angular 1.x ...

function isDefined(value) {return typeof value !== 'undefined';}

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

ฉันยังเพิ่มส่วนนี้จาก MDN ซึ่งได้รับข้อมูลที่เป็นประโยชน์เกี่ยวกับ typeof, undefined และ void (0)

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

var x;
if (x === undefined) {
   // these statements execute
}
else {
   // these statements do not execute
}

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


Typeof operator และ undefined
อีกทางเลือกหนึ่ง typeof สามารถใช้:

var x;
if (typeof x === 'undefined') {
   // these statements execute
}

เหตุผลหนึ่งที่ใช้ typeof คือมันไม่ได้เกิดข้อผิดพลาดหากยังไม่ได้ประกาศตัวแปร

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
   // these statements execute
}

if (x === undefined) { // throws a ReferenceError

}

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


ผู้ประกอบการโมฆะและไม่ได้กำหนด

ตัวดำเนินการ void เป็นทางเลือกที่สาม

var x;
if (x === void 0) {
   // these statements execute
}

// y has not been declared before
if (y === void 0) {
   // throws a ReferenceError (in contrast to `typeof`)
}

เพิ่มเติม> ที่นี่


13

' if (window.x) {} ' มีข้อผิดพลาดที่ปลอดภัย

if (window.x)ส่วนใหญ่มีแนวโน้มที่คุณต้องการ การตรวจสอบนี้ปลอดภัยแม้ว่า x จะไม่ถูกประกาศ ( var x;) - เบราว์เซอร์ไม่ได้เกิดข้อผิดพลาด

ตัวอย่าง: ฉันต้องการทราบว่าเบราว์เซอร์ของฉันรองรับ History API หรือไม่

if (window.history) {
    history.call_some_function();
}

มันทำงานอย่างไร:

windowเป็นวัตถุที่เก็บตัวแปรส่วนกลางทั้งหมดในฐานะสมาชิกและเป็นกฎหมายที่พยายามเข้าถึงสมาชิกที่ไม่มีอยู่ ถ้าxยังไม่ได้รับการประกาศหรือยังไม่ได้รับการตั้งค่าแล้วwindow.xกลับไม่ได้กำหนด ไม่ได้กำหนดจะนำไปสู่falseเมื่อif ()ประเมินค่า


แต่ถ้าคุณใช้ Node ล่ะ typeof history != 'undefined'ใช้งานได้จริงในทั้งสองระบบ
Stijn de Witt

13

การอ่านผ่านสิ่งนี้ฉันประหลาดใจที่ฉันไม่เห็นสิ่งนี้ ฉันพบอัลกอริทึมหลายอย่างที่สามารถใช้ได้กับสิ่งนี้

ไม่เคยกำหนด

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

if(obj.prop === void 0) console.log("The value has never been defined");

กำหนดเป็นไม่ได้กำหนดหรือไม่เคยกำหนด

หากคุณต้องการให้ผลลัพธ์เป็นtrueค่าที่กำหนดด้วยค่าundefinedหรือไม่เคยกำหนดไว้คุณสามารถใช้=== undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

กำหนดเป็นค่าที่ไม่ถูกต้องไม่ได้กำหนดเป็นโมฆะหรือไม่เคยกำหนดไว้

โดยทั่วไปผู้คนถามฉันถึงอัลกอริทึมที่จะเข้าใจว่าค่านั้นผิดพลาดundefinedหรือnullไม่ ผลงานดังต่อไปนี้

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}

4
ฉันคิดว่าคุณสามารถแทนที่ตัวอย่างสุดท้ายด้วยif (!obj.prop)
Stijn de Witt

@StijndeWitt คุณสามารถผมมือใหม่สวยเมื่อผมเขียนนี้และภาษาอังกฤษของฉันดูเหมือนว่าจะได้รับที่ไม่ดีอย่างเท่าเทียมกัน แต่มีอะไรที่ไม่ถูกต้องในคำตอบ
เทรวิส

3
var obj = {foo: undefined}; obj.foo === void 0true-> "ไม่เคยนิยามว่าundefined" เป็นอย่างไร นี่เป็นสิ่งที่ผิด
Patrick Roberts

@PatrickRoberts คุณพูดถูก เมื่อฉันเขียนคำตอบนี้ในเดือนกุมภาพันธ์ 2558 (ก่อน ES6) ตัวเลือกแรกที่ฉันสรุปไว้ใช้งานได้จริง แต่ตอนนี้ล้าสมัยแล้ว
เทรวิส


10

เปรียบเทียบกับvoid 0เพื่อความกระชับ

if (foo !== void 0)

มันไม่ได้เป็นอย่าง verbose if (typeof foo !== 'undefined')


3
แต่มันจะส่ง ReferenceError ถ้าfooไม่ได้ประกาศ
daniel1426

1
@ daniel1426: ดังนั้นหากมีข้อผิดพลาดในรหัสของคุณคุณต้องการซ่อนไว้แทนที่จะแก้ไขหรือไม่ ไม่ใช่วิธีการที่ยอดเยี่ยม IMO

สิ่งนี้ไม่ได้ใช้เพื่อซ่อนข้อผิดพลาด เป็นวิธีการทั่วไปในการตรวจสอบคุณสมบัติของสภาพแวดล้อมในการกำหนด polyfills ตัวอย่างเช่น: if (typeof Promise === 'undefined') {/ * define Promise * /}
gaperton

10

วิธีแก้ไขไม่ถูกต้อง ในจาวาสคริปต์

null == undefined

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

if (something === undefined)

ซึ่งเป็นผู้ประกอบการประจำตัว ...


3
เพื่อให้ชัดเจน===คือ type equality + (primitive equality | object identity) โดยที่ primitives จะมีสตริง ฉันคิดว่าคนส่วนใหญ่พิจารณาว่าใช้งาน'abab'.slice(0,2) === 'abab'.slice(2)ไม่ได้ง่ายถ้าใครคิด===ว่าเป็นตัวดำเนินการระบุตัวตน
clacke

1
ไม่ถูกต้อง. สิ่งนี้จะโยนข้อผิดพลาดหากยังไม่ได้สร้างตัวแปร ไม่ควรลงคะแนน ใช้ typeof แทน
Simon East

10

คุณสามารถรับอาเรย์ทั้งหมดที่ไม่ได้กำหนดด้วยพา ธ โดยใช้รหัสต่อไปนี้

 function getAllUndefined(object) {

        function convertPath(arr, key) {
            var path = "";
            for (var i = 1; i < arr.length; i++) {

                path += arr[i] + "->";
            }
            path += key;
            return path;
        }


        var stack = [];
        var saveUndefined= [];
        function getUndefiend(obj, key) {

            var t = typeof obj;
            switch (t) {
                case "object":
                    if (t === null) {
                        return false;
                    }
                    break;
                case "string":
                case "number":
                case "boolean":
                case "null":
                    return false;
                default:
                    return true;
            }
            stack.push(key);
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    v = getUndefiend(obj[k], k);
                    if (v) {
                        saveUndefined.push(convertPath(stack, k));
                    }
                }
            }
            stack.pop();

        }

        getUndefiend({
            "": object
        }, "");
        return saveUndefined;
    }

ลิงก์jsFiddle


ในขณะที่มันจะไม่ส่งผลกระทบต่อความถูกต้องของรหัสของคุณคุณจะได้มีการพิมพ์ผิด: ควรจะเป็นgetUndefiend getUndefined
icktoofay

8

นี่คือสถานการณ์ของฉัน:

ฉันกำลังใช้ผลการโทร REST ควรแยกวิเคราะห์ผลลัพธ์จาก JSON ไปยังวัตถุ JavaScript

มีข้อผิดพลาดประการหนึ่งที่ฉันต้องปกป้องคือ หาก args ไปยังการโทรที่เหลือไม่ถูกต้องเท่าที่ผู้ใช้ระบุ args ผิดการโทรที่เหลือจะกลับมาว่างเปล่าโดยทั่วไป

ในขณะที่ใช้โพสต์นี้เพื่อช่วยฉันป้องกันสิ่งนี้ฉันพยายามทำสิ่งนี้

if( typeof restResult.data[0] === "undefined" ) { throw  "Some error"; }

สำหรับสถานการณ์ของฉันถ้า restResult.data [0] === "วัตถุ" จากนั้นฉันสามารถเริ่มตรวจสอบสมาชิกที่เหลือได้อย่างปลอดภัย หากไม่ได้กำหนดให้โยนข้อผิดพลาดดังกล่าวข้างต้น

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


typeofยามของคุณไม่ได้ป้องกันสิ่งใดที่การเปรียบเทียบโดยตรงไม่สามารถจัดการได้ หากrestResultไม่ได้กำหนดหรือไม่ได้ประกาศก็จะยังคงโยน

ในกรณีของคุณคุณมากขึ้นก็สามารถตรวจสอบว่าอาร์เรย์ว่างเปล่า:if(!restResult.data.length) { throw "Some error"; }
Headbank

8

มีวิธีที่ดี & สวยงามในการกำหนดคุณสมบัติที่กำหนดให้กับตัวแปรใหม่หากมีการกำหนดหรือกำหนดค่าเริ่มต้นให้กับมันเป็นทางเลือกหากไม่ได้กำหนด

var a = obj.prop || defaultValue;

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

var yourFunction = function(config){

   this.config = config || {};
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

}

ตอนนี้กำลังดำเนินการ

yourFunction({yourConfigValue:2});
//=> 2

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1

7

คำตอบทั้งหมดไม่สมบูรณ์ นี่เป็นวิธีที่ถูกต้องในการรู้ว่ามีคุณสมบัติ 'กำหนดเป็นไม่ได้กำหนด':

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop){
  return ((prop in obj) && (typeof obj[prop] == 'undefined')) ;
} ;

ตัวอย่าง:

var a = { b : 1, e : null } ;
a.c = a.d ;

hasUndefinedProperty(a, 'b') ; // false : b is defined as 1
hasUndefinedProperty(a, 'c') ; // true : c is defined as undefined
hasUndefinedProperty(a, 'd') ; // false : d is undefined
hasUndefinedProperty(a, 'e') ; // false : e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c') ; // false : c is undefined

น่าเสียดายที่คำตอบนี้ถูกฝังอยู่ในคำตอบที่ผิด> _ <

ดังนั้นสำหรับทุกคนที่ผ่านไปฉันจะให้คุณไม่ได้กำหนดฟรี !!

var undefined ; undefined ; // undefined
({}).a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function(){}()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined

7

จะผ่านความคิดเห็นสำหรับผู้ที่ต้องการตรวจสอบทั้งสองมันไม่ได้กำหนดหรือค่าเป็นโมฆะ:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

หากคุณกำลังใช้ jQuery Library jQuery.isEmptyObject()จะเพียงพอสำหรับทั้งสองกรณี

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;

jQuery จะดูแลปัญหาความเข้ากันได้ข้ามเบราว์เซอร์กับ JavaScript API ที่แตกต่างกัน
Henry Heleine

7

หากคุณใช้แองกูลาร์:

angular.isUndefined(obj)
angular.isUndefined(obj.prop)

Underscore.js:

_.isUndefined(obj) 
_.isUndefined(obj.prop) 

2
ฉันจะเพิ่ม1ตัวแปรxอย่างไร ฉันต้องการขีดล่างหรือ jQuery หรือไม่ (น่าทึ่งที่ผู้คนจะใช้ห้องสมุดสำหรับแม้แต่การดำเนินการขั้นพื้นฐานที่สุดเช่นการtypeofตรวจสอบ)
Stijn de Witt

6

ฉันใช้if (this.variable)เพื่อทดสอบว่ามีการกำหนดไว้หรือไม่ ที่เรียบง่ายif (variable), ที่แนะนำข้างต้นล้มเหลวสำหรับฉัน ปรากฎว่ามันทำงานเฉพาะเมื่อตัวแปรเป็นเขตข้อมูลของวัตถุบางอย่างobj.someFieldเพื่อตรวจสอบว่ามีการกำหนดไว้ในพจนานุกรม แต่เราสามารถใช้thisหรือwindowเป็นวัตถุพจนานุกรมเนื่องจากตัวแปรใด ๆ เป็นเขตข้อมูลในหน้าต่างปัจจุบันตามที่ฉันเข้าใจ ดังนั้นนี่คือการทดสอบ

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

ก่อนตรวจพบว่าตัวแปรabcไม่ได้ถูกกำหนดและถูกกำหนดหลังจากการเริ่มต้น


5

ฉันให้สามวิธีที่นี่สำหรับผู้ที่คาดหวังคำตอบแปลก ๆ :

function isUndefined1(val) {
    try {
        val.a;
    } catch (e) {
        return /undefined/.test(e.message);
    }
    return false;
}
function isUndefined2(val) {
    return !val && val+'' === 'undefined';
}
function isUndefined3(val) {
    const defaultVal={};
    return ((input=defaultVal)=>input===defaultVal)(val);
}
function test(func){
    console.group(`test start :`+func.name);
    console.log(func(undefined));
    console.log(func(null));
    console.log(func(1));
    console.log(func("1"));
    console.log(func(0));
    console.log(func({}));
    console.log(func(function () { }));
    console.groupEnd();
}
test(isUndefined1);
test(isUndefined2);
test(isUndefined3);

isUndefined1:

ลองรับคุณสมบัติของค่าอินพุตตรวจสอบข้อความแสดงข้อผิดพลาดหากมีอยู่ หากค่าอินพุตไม่ได้กำหนดข้อความแสดงข้อผิดพลาดจะเป็น Uncaught TypeError: ไม่สามารถอ่านคุณสมบัติ 'b' ของไม่ได้กำหนด

isUndefined2:

แปลงค่าอินพุตเป็นสตริงเพื่อเปรียบเทียบ"undefined"และตรวจสอบให้แน่ใจว่าเป็นค่าลบ

isUndefined3:

ใน js, undefinedพารามิเตอร์ตัวเลือกทำงานเมื่อค่าเข้าเป็นว่า


4
function isUnset(inp) {
  return (typeof inp === 'undefined')
}

ส่งคืนเท็จถ้าตั้งค่าตัวแปรและเป็นจริงถ้าไม่ได้กำหนด

จากนั้นใช้:

if (isUnset(var)) {
  // initialize variable here
}

5
ไม่อย่าทำอย่างนี้ ใช้การทดสอบอย่างง่าย ๆ เพียงเพื่อพิสูจน์ว่าคุณไม่สามารถสรุปการtypeofทดสอบในฟังก์ชันได้อย่างมีความหมาย น่าอัศจรรย์ที่ 4 คนโหวตสิ่งนี้ -1
Stijn de Witt

4

ฉันต้องการแสดงสิ่งที่ฉันใช้เพื่อปกป้องundefinedตัวแปร:

Object.defineProperty(window, 'undefined', {});

สิ่งนี้ห้ามมิให้ผู้ใดเปลี่ยนwindow.undefinedค่าดังนั้นการทำลายโค้ดตามตัวแปรนั้น หากใช้"use strict"สิ่งใดก็ตามที่พยายามเปลี่ยนค่าจะสิ้นสุดลงโดยผิดพลาดมิฉะนั้นจะถูกเพิกเฉย


4

คุณยังสามารถใช้พร็อกซีมันจะทำงานกับการโทรซ้อน แต่จะต้องมีการตรวจสอบเพิ่มเติมหนึ่งรายการ:

function resolveUnknownProps(obj, resolveKey) {
  const handler = {
    get(target, key) {
      if (
        target[key] !== null &&
        typeof target[key] === 'object'
      ) {
        return resolveUnknownProps(target[key], resolveKey);
      } else if (!target[key]) {
        return resolveUnknownProps({ [resolveKey]: true }, resolveKey);
      }

      return target[key];
    },
  };

  return new Proxy(obj, handler);
}

const user = {}

console.log(resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else); // { isUndefined: true }

ดังนั้นคุณจะใช้มันเหมือน:

const { isUndefined } = resolveUnknownProps(user, 'isUndefined').personalInfo.name.something.else;
if (!isUndefined) {
  // do someting
}

4

จาก lodash.js

var undefined;
function isUndefined(value) {
  return value === undefined;
}

มันจะสร้างตัวแปรท้องถิ่นชื่อundefinedซึ่งจะเริ่มต้นได้ด้วยค่าเริ่มต้น - จริงundefinedแล้วเปรียบเทียบกับตัวแปรvalueundefined


อัปเดต 9/9/2019

ฉันพบว่า lodash ได้อัปเดตการใช้งาน ดูปัญหาของฉันและรหัส

เพื่อเป็นหลักฐานกระสุนเพียงใช้:

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