typeof! ==“ undefined” กับ! = null


491

ฉันมักจะเห็นรหัส JavaScript ซึ่งตรวจสอบพารามิเตอร์ที่ไม่ได้กำหนด ฯลฯ ด้วยวิธีนี้:

if (typeof input !== "undefined") {
    // do stuff
}

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

คำถามของฉันคือ:
รหัสนั้นดีกว่าวิธีนี้ได้อย่างไร:

if (null != input) {
    // do stuff
}

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

ทว่ารูปแบบนี้ยังไม่แพร่หลายและทำให้ JSLint ตะโกนใส่คุณเพื่อใช้ตัว!=ดำเนินการร้าย

ทำไมสิ่งนี้จึงถือว่าเป็นรูปแบบที่ไม่ดี


13
@ Marcel ไม่มีความแตกต่างจริง แต่มีสองเหตุผลที่จะทำ หนึ่งคือสำหรับบางคนมันชัดเจนในการอ่าน และเหตุผลที่สองคือป้องกันการเขียนทับตัวแปรโดยไม่ตั้งใจ คุณเคยทำสิ่งนี้หรือไม่: ถ้า (foo = "value") เมื่อตั้งใจจะทำการเปรียบเทียบ หากคุณมีพฤติกรรมการย้อนกลับตัวแปรในตัวดำเนินการกำหนด / การเปรียบเทียบคุณจะไม่มีปัญหานั้น
Layke

29
สำหรับบางคน (รวมถึงฉัน) นี่เป็นเรื่องยากที่จะอ่าน นอกจากนี้ IDEs ส่วนใหญ่ยังเตือนคุณถึงการได้รับมอบหมายโดยไม่ตั้งใจ แต่ฉันยังคงใช้แบบฟอร์มนี้หากตัวแปรเปรียบเทียบยาวมาก YMMV
johndodo

15
@MarcelKorpel สิ่งนี้เรียกว่า "Yoda condition": umumble.com/blogs/Programming/321
kol

55
อ่านยากกว่า ไม่มีใครพูดว่า "ขวดเปล่า"
Noel Abrahams

11
if (null != input)เป็นเพียง "โยดาพูด" กับผู้พูดภาษาอังกฤษ (หนึ่งในฉันคือ .... uuammmmm) ดังนั้นหากพวกเขาถือเอาสิ่งเดียวกันมันเป็นความหมายจริงๆ IMHO
webLacky3rdClass

คำตอบ:


709

typeof ปลอดภัยกว่าเนื่องจากอนุญาตให้ตัวระบุไม่เคยมีการประกาศมาก่อน:

if(typeof neverDeclared === "undefined") // no errors

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined

3
if ((typeof neverDeclared! == "undefined") && (neverDeclared! == null)) {return true; } else {return false; }
Anthony DiSanti

88
ใช้ === เมื่อเปรียบเทียบกับ null / undefined
MyGGaN

47
@MyGGaN เฉพาะในกรณีที่คุณต้องการแยกความแตกต่างระหว่างทั้งสอง ในหลายกรณี==อาจดีกว่าเพราะทดสอบทั้งค่าว่างและไม่ได้กำหนด
seanmonstar

10
ฉันไม่พบความแตกต่างระหว่าง typeof somevar == 'undefined' และ typeof somevar === 'undefined' เนื่องจาก typeof ส่งคืนสตริงเสมอ สำหรับ null มันจะส่งกลับ 'วัตถุ' หรืออาจเป็นได้ว่าฉันผิด
TomTom

2
ฉันเชื่อว่าความคิดเห็นของ @ TomTom เป็นจุดเริ่มต้นของปัญหา - ฉันไม่สามารถเข้าใจได้ว่าทำไมใครจะใช้!==หรือ===โอเปอเรเตอร์เมื่อเปรียบเทียบค่าที่ทราบว่าเป็นประเภทสตริง
Nicolas Rinaudo

49

หากมีการประกาศตัวแปร (ด้วยvarคำหลักเป็นอาร์กิวเมนต์ของฟังก์ชันหรือเป็นตัวแปรกลาง) ฉันคิดว่าวิธีที่ดีที่สุดคือ:

if (my_variable === undefined)

jQuery ทำดังนั้นจึงดีพอสำหรับฉัน :-)

มิฉะนั้นคุณจะต้องใช้เพื่อหลีกเลี่ยงการtypeofReferenceError

หากคุณคาดว่าจะไม่ได้กำหนดจะถูกนิยามใหม่คุณสามารถใส่รหัสของคุณดังนี้:

(function(undefined){
    // undefined is now what it's supposed to be
})();

หรือรับมันผ่านvoidโอเปอเรเตอร์:

const undefined = void 0;
// also safe

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

20
@Anthony DiSanti: ไม่undefinedเป็นชื่อที่กำหนดให้กับพารามิเตอร์ฟังก์ชันไม่ใช่ค่า ไม่มีการส่งผ่านไปยังฟังก์ชันหมายความว่าค่าของพารามิเตอร์แรกไม่ได้ถูกกำหนด
Joey Adams

3
ความผิดพลาดของฉันขอบคุณสำหรับการติดตาม ฉันลบคะแนนของฉันลงแล้วขออภัยด้วย
Anthony DiSanti

2
เหตุใดจึงเขียนข้อยกเว้นเพื่อจัดการกับผู้พัฒนารายอื่นที่ไม่ได้กำหนดซึ่งประกาศเมื่อคุณสามารถทำได้อย่างถูกต้องเพื่อเริ่มต้นด้วย jQuery ล้อมรอบฟังก์ชันที่ไม่ระบุชื่อเริ่มต้นตามที่คุณแสดงในฟังก์ชั่นของคุณเพื่อให้แน่ใจว่าไม่ได้กำหนดไม่ได้กำหนดและเพื่อลดขนาดย่อ เพียงแค่ใส่ถ้ามันสามารถให้ผลลัพธ์ที่ไม่คาดคิดได้ด้วยวิธีนี้เหตุใดจึงเสี่ยงต่อการเขียนโปรแกรมขี้เกียจเพื่อหลีกเลี่ยงการพิมพ์ออกมา (ตัวแปร typeof === 'undefined') ถ้าเราต้องการ (typeof variable === 'object') เราควรจะจัดเตรียมตัวแปรเริ่มต้นที่เป็นอ็อบเจกต์ด้วยเพื่อที่เราจะได้ทำ (ตัวแปร === object)?
fyrye

28

วิธีที่ดี:

if(typeof neverDeclared == "undefined") //no errors

แต่วิธีที่ดีที่สุดคือตรวจสอบผ่าน:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings

6
var undefined = function () {}; if (typeof neverDeclared === typeof undefined); neverDecalred! = 'function'; jsfiddle.net/hbPZ5ส่งคืนชนิดของ var; ส่งคืนสตริง ไม่มีข้อผิดพลาดหรือสตริง แต่จะไม่ให้ผลลัพธ์ที่คาดหวังเสมอไป นักพัฒนาที่ได้รับควรไม่ประกาศไม่ได้กำหนด แต่มีบางเฟรมและไลบรารีที่ทำ
fyrye

1
ฉันใช้เป็นหลัก if (typeof neverDeclared === typeof undefined) { แต่ผ้าสำลีเกิดข้อผิดพลาด "คาดหวังสตริงและเห็น 'typeof' แทน" คุณจะแก้ไขข้อผิดพลาดนี้ได้อย่างไร? เราควรส่งคำขอของ Lint และใช้ 'วิธีที่ดี' แทนหรือไม่
Ayelis

2
@fyrye คุณรู้จักไลบรารี / กรอบงาน JavaScript ใดที่กลายพันธุ์ไม่ได้กำหนดจริง ฉันรู้ว่ามันเป็นไปได้ แต่ฉันต้องการที่จะหาตัวอย่างในป่าของ "นี่คือที่ที่คุณอาจพบ Wildebeest น่ารังเกียจนี้!"
bigtunacan

4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich

1
มันเป็นข้อผิดพลาดได้ง่ายเพราะในความเป็นจริงคุณเพิ่งพึ่งตัวแปรบางตัว ("ไม่ได้กำหนด") ซึ่งไม่ได้ถูกกำหนดไว้ ซึ่งอาจเป็นเท็จตามที่โพสต์อื่นแสดงให้เห็น คุณสามารถทำได้if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {แต่มันค่อนข้างนาน
Pierre-Olivier Vares

12

คุณไม่ควรกังวลเกี่ยวกับการเปลี่ยนชื่อไม่ได้กำหนด หากมีคนเปลี่ยนชื่อไม่ได้กำหนดคุณจะประสบปัญหามากกว่าการตรวจสอบที่ล้มเหลว หากคุณต้องการปกป้องรหัสของคุณให้ห่อด้วย IFFE (ฟังก์ชั่นที่เรียกใช้ในทันที) เช่นนี้:

(function($, Backbone, _, undefined) {
    //undefined is undefined here.
})(jQuery, Backbone, _);

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

if(window.neverDefined === undefined) {
    //Code works
}

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

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


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

ดูเหมือนคุณอาจจำเป็นต้องใช้สิ่งที่อยู่ในสายของเอเอ็มดี (require.js)
Peeter

1
หรือฉันอาจจะเพียงแค่ต้องการที่จะทำเปรียบเทียบง่ายมากมากกว่ารวมทั้งห้องสมุดอื่นในโครงการของฉัน :)
AmericanUmlaut

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

1
ไม่เพราะ typeof ส่งคืนสตริง ดังนั้น typeof undefined จะส่งคืน "undefined" window.input! == undefined (หากตัวแปรของคุณอยู่ในระดับโลก)
Peeter

5

หากคุณกังวลเกี่ยวกับการไม่ได้ถูกนิยามใหม่คุณสามารถป้องกันด้วยวิธีการช่วยเหลือบางอย่างเช่นนี้:

function is_undefined(value) {
   var undefined_check; // instantiate a new variable which gets initialized to the real undefined value
   return value === undefined_check;
}

งานนี้เพราะเมื่อมีคนเขียนundefined = "foo"เขาเท่านั้นที่จะช่วยให้ชื่อ undefinedอ้างอิงถึงค่าใหม่ undefinedแต่เขาไม่ได้เปลี่ยนแปลงมูลค่าที่แท้จริงของ


1
อย่างไรก็ตามคุณได้แนะนำการเรียกใช้ฟังก์ชันซึ่งจะเป็นอันตรายต่อประสิทธิภาพการทำงาน
Tim Down

ฉันไม่คิดว่าการเรียกฟังก์ชั่นนี้จะทำให้ประสิทธิภาพลดลงมีความเป็นไปได้มากกว่าที่ DOM จะเป็นคอขวด แต่อย่างไรก็ตามถ้าคุณมีฟังก์ชั่นนิรนามขนาดใหญ่ตามปกติซึ่งมีไลบรารี่ของคุณคุณก็สามารถกำหนดundefined_checkที่ด้านบนแล้วใช้มันทุกที่ในโค้ดของคุณ
Ivo Wetzel

1
ตกลงและฉันไม่ได้บอกว่านี่เป็นความคิดที่ไม่ดี เป็นเพียงการชี้ให้เห็นว่าการเรียกใช้ฟังก์ชันนี้จะทำงานช้ากว่าการtypeofตรวจสอบ
Tim Down

ฉันคิดว่าฟังก์ชั่นนี้ง่ายพอที่มันจะถูกแทรกเพื่อประสิทธิภาพจะไม่ได้รับผลกระทบ
huyz

4
@TimDown: เขียนโค้ดครั้งแรกซึ่งสามารถอ่านได้ เขียนรหัสที่สองนั่นคือการบำรุงรักษาแล้วถ้ามันช้าจริงๆ จากนั้นคิดเกี่ยวกับประสิทธิภาพ
Andreas

4

คุณยังสามารถใช้ตัวดำเนินการ void เพื่อรับค่าไม่ได้กำหนด:

if (input !== void 0) {
    // do stuff    
}

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


1

ฉันเคยเจอจริง ๆ แล้วถ้า(typeof input !== 'undefined')ในสถานการณ์นี้ที่มันถูกใช้เพื่อให้พารามิเตอร์ฟังก์ชันเริ่มต้น:

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

ES6 มีวิธีใหม่ในการแนะนำพารามิเตอร์ฟังก์ชันเริ่มต้นด้วยวิธีนี้:

function greet(name = 'Student', greeting = 'Welcome') {
  return `${greeting} ${name}!`;
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

นี่คือ verbose น้อยและสะอาดกว่าตัวเลือกแรก


1

function greet(name, greeting) {
  name = (typeof name !== 'undefined') ?  name : 'Student';
  greeting = (typeof greeting !== 'undefined') ?  greeting : 'Welcome';

  console.log(greeting,name);
}

greet(); // Welcome Student!
greet('James'); // Welcome James!
greet('Richard', 'Howdy'); // Howdy Richard!

//ES6 provides new ways of introducing default function parameters this way:

function greet2(name = 'Student', greeting = 'Welcome') {
//  return '${greeting} ${name}!';
console.log(greeting,name);
}

greet2(); // Welcome Student!
greet2('James'); // Welcome James!
greet2('Richard', 'Howdy'); // Howdy Richard!


0

(function(){

  var a= b = 3;
  var ed = 103;
  
})();



//console.log(ed); //ed is not defined

console.log("a defined? " + (typeof a !== 'undefined')); //no define
console.log("b defined? " + (typeof b !== 'undefined')); //yes define
console.log(typeof(b)); //number
console.log(typeof(4+7));   //number
console.log(b); //3
console.log(typeof("4"+"7")); //string
var e= "ggg";
console.log(typeof(e)); //string
 var ty=typeof(b);
console.log(ty); //number
console.log(typeof false); //boolean
console.log(typeof 1); //number
console.log(typeof 0); //number
console.log(typeof true); //boolean


console.log(typeof Math.tan);  //function
console.log(typeof function(){}); //function 

if(typeof neverDeclared == "undefined") //no errors
if(typeof neverDeclared === "undefined") //no errors

//if(neverDeclared == null) //showing error 


console.log(typeof {a:1}); //object
console.log(typeof null); //object
console.log(typeof JSON); //object
console.log(typeof Math); //object
console.log(typeof /a-z/); //object
console.log(typeof new Date()); //object

console.log(typeof afbc); //undefined
//console.log(typeof new);//error

document.write("<br> * oprator as math ");
var r=14*"4";
document.write(r);

document.write("<br> + oprator as string ");
var r=14+"44";
document.write(r);

document.write("<br> Minus Operator work as mathematic ");
var r=64-"44";
document.write(r);


document.write("<br>");
console.log(typeof(4*"7")); //returns number
console.log(typeof(4+"7")); //returns string




 
Interview Question in JavaScript


คุณสามารถให้คำอธิบายได้หรือไม่?
jhpratt GOFUNDME RELICENSING

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

0

var bar = null;
console.log(typeof bar === "object"); //true yes 
//because null a datatype of object

var barf = "dff";
console.log(typeof barf.constructor);//function


console.log(Array.isArray(bar));//falsss


console.log((bar !== null) && (bar.constructor === Object)); //false

console.log((bar !== null) && (typeof bar === "object"));  // logs false
//because bar!==null, bar is a object


console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function"))); //false

console.log(typeof bar === typeof object); //false
console.log(typeof bar2 === typeof undefined); //true
console.log(typeof bar3 === typeof undefinedff); //true
console.log(typeof bar2 == typeof undefined); //true

console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]")); //false


-7
if (input == undefined) { ... }

ทำงานได้ดี แน่นอนว่าไม่ใช่การnullเปรียบเทียบ แต่โดยทั่วไปฉันพบว่าหากฉันต้องการแยกแยะระหว่างundefinedและnullจริง ๆ แล้วฉันต้องแยกความแตกต่างระหว่างundefinedและเป็นค่าเท็จดังนั้น

else if (input) { ... }

ทำมัน.

หากโปรแกรมกำหนดใหม่undefinedมันเป็นเรื่องจริงที่ว่า

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

var undefined;

และการเปรียบเทียบข้างต้นก็ใช้ได้ดี

ในตัวอย่างที่สองของคุณคุณอาจต้องใช้วงเล็บคู่เพื่อให้ผ้าสำลีมีความสุข?


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