typeof! == “undefined” vs.! = null

491

Saya sering melihat kode JavaScript yang memeriksa parameter yang tidak ditentukan, dll. Dengan cara ini:

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

Ini sepertinya agak boros, karena melibatkan pencarian tipe dan perbandingan string, belum lagi verbositasnya. Itu diperlukan karenaundefined bisa diubah namanya.

Pertanyaan saya adalah:
Bagaimana kode itu lebih baik daripada pendekatan ini:

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

Sejauh yang saya tahu, Anda tidak dapat mendefinisikan ulang null, jadi itu tidak akan rusak secara tak terduga. Dan, karena jenis-paksaan dari !=operator, ini memeriksa keduanya undefineddan null... yang sering kali persis seperti yang Anda inginkan (misalnya untuk parameter fungsi opsional).

Namun formulir ini tampaknya tidak tersebar luas, dan bahkan menyebabkan JSLint berteriak kepada Anda karena menggunakan !=operator jahat .

Mengapa ini dianggap gaya yang buruk?

Derek Thurn
sumber
13
@ Marcel, tidak ada perbedaan nyata, tetapi ada dua alasan untuk melakukannya. Pertama, bagi sebagian orang itu lebih jelas dibaca. Dan alasan kedua, adalah bahwa hal itu mencegah overwriting variabel secara tidak sengaja. Pernahkah Anda melakukan ini: if (foo = "value") ketika hendak melakukan perbandingan. Jika Anda terbiasa membalik variabel, di operator penugasan / pembanding, maka Anda tidak akan memiliki masalah itu.
Layke
29
Bagi sebagian orang (termasuk saya) ini sebenarnya lebih sulit dibaca. Juga, sebagian besar IDE memperingatkan Anda tentang tugas yang tidak disengaja. Tapi saya masih menggunakan formulir ini jika variabel yang dibandingkan sangat panjang. YMMV.
johndodo
15
@MarcelKorpel Ini disebut "Yoda condition": umumble.com/blogs/Programming/321
kol
55
Lebih sulit dibaca. Orang tidak mengatakan "Tidak kosong adalah botol".
Noel Abrahams
11
if (null != input)hanya "Yoda Speak" untuk penutur bahasa Inggris (Dari satu aku .... uuammmmm) jadi jika mereka menyamakan hal yang sama itu benar-benar hanya semantik. MENURUT OPINI SAYA.
webLacky3rdClass

Jawaban:

710

typeof lebih aman karena memungkinkan pengidentifikasi tidak pernah dideklarasikan sebelumnya:

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

if(neverDeclared === null) // throws ReferenceError: neverDeclared is not defined
seanmonstar
sumber
3
if ((typeof neverDeclared! == "undefined") && (neverDeclared! == null)) {return true; } else {return false; }
Anthony DiSanti
88
Gunakan === saat membandingkan dengan null / undefined.
MyGGaN
47
@MyGGaN hanya jika Anda ingin membedakan keduanya. Dalam banyak kasus, ==bisa lebih baik, karena ia menguji null dan tidak terdefinisi.
seanmonstar
10
Saya tidak dapat menemukan perbedaan antara typeof somevar == 'undefined' dan typeof somevar === 'undefined', karena typeof selalu mengembalikan string. Untuk null akan mengembalikan 'objek'. Atau bisa jadi saya salah?
TomTom
2
Saya percaya komentar @TomTom sebagai inti dari masalah - saya tidak bisa mengerti mengapa orang akan menggunakan !==atau ===operator ketika membandingkan nilai yang jenisnya dikenal sebagai string.
Nicolas Rinaudo
49

Jika variabel dinyatakan (baik dengan varkata kunci, sebagai argumen fungsi, atau sebagai variabel global), saya pikir cara terbaik untuk melakukannya adalah:

if (my_variable === undefined)

jQuery melakukannya, jadi itu cukup baik untuk saya :-)

Jika tidak, Anda harus menggunakan typeofuntuk menghindari a ReferenceError.

Jika Anda berharap tidak terdefinisi ulang, Anda dapat membungkus kode Anda seperti ini:

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

Atau dapatkan melalui voidoperator:

const undefined = void 0;
// also safe
Joey Adams
sumber
1
Jika undefined telah didefinisikan, maka bukankah Anda akan meneruskannya ke fungsi anonim Anda melalui parameter bernama undefined, tidak menyelesaikan apa pun?
Anthony DiSanti
20
@Anthony DiSanti: Tidak, undefinedadalah nama yang diberikan ke parameter fungsi, bukan nilainya. Tidak ada yang diteruskan ke fungsi, artinya nilai parameter pertama tidak terdefinisi.
Joey Adams
3
Ah kesalahan saya, terima kasih telah menindaklanjuti. Saya telah menghapus suara saya, maaf tentang itu.
Anthony DiSanti
2
Mengapa menulis pengecualian untuk menangani undefined yang dideklarasikan oleh pengembang lain padahal Anda bisa melakukannya dengan benar? jQuery membungkus fungsi anonim awal seperti yang Anda tunjukkan di fungsi Anda untuk memastikan undefined tidak didefinisikan dan untuk mengurangi ukuran yang diperkecil. Sederhananya jika itu dapat memberikan hasil yang tidak terduga untuk melakukannya dengan cara ini, mengapa berisiko untuk pemrograman malas untuk menghindari mengetik (typeof variabel === 'tidak terdefinisi'). Bagaimana jika kita ingin (typeof variabel === 'objek') haruskah kita memberikan variabel default yang merupakan objek juga sehingga kita dapat melakukan (variabel === objek)?
fyrye
28

Cara yang baik:

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

Tetapi cara terbaik adalah memeriksa melalui:

if(typeof neverDeclared === typeof undefined) //also no errors and no strings
Lelucon
sumber
6
var undefined = function () {}; if (typeof neverDeclared === typeof undefined); neverDecalred! = 'function'; jsfiddle.net/hbPZ5 mengembalikan typeof var; mengembalikan sebuah string. Tidak ada kesalahan atau string tetapi tidak akan selalu memberikan hasil yang diharapkan. Pengembang yang diberikan seharusnya tidak menyatakan tidak terdefinisi, tetapi ada beberapa kerangka kerja dan perpustakaan yang melakukannya.
fyrye
1
Saya terutama menggunakan if (typeof neverDeclared === typeof undefined) { tetapi Lint melempar kesalahan. "Diharapkan sebuah string dan bukannya melihat 'typeof'." Bagaimana Anda mengatasi kesalahan ini? Haruskah kita tunduk pada permintaan Lint dan menggunakan 'cara yang baik' sebagai gantinya?
Ayelis
2
@fyrye Apakah Anda tahu ada pustaka / kerangka kerja JavaScript yang sebenarnya bermutasi tidak terdefinisi? Saya tahu itu mungkin; tapi saya ingin menemukan dalam contoh liar, "Di sinilah Anda mungkin menemukan Wildebeest jahat ini!"
bigtunacan
4
typeof neverDeclared === typeof void 0;-D
Alex Yaroshevich
1
Ini rawan kesalahan, karena sebenarnya Anda hanya mengandalkan variabel tertentu ("tidak terdefinisi") yang tidak didefinisikan. Yang bisa salah, seperti yang ditunjukkan oleh pos lainnya. Anda selalu bisa melakukannya if(typeof neverDeclared === typeof undefined_variable_with_a_name_assumed_to_be_never_defined) {tetapi itu agak panjang.
Pierre-Olivier Vares
12

Anda tidak perlu khawatir tentang penggantian nama yang tidak ditentukan. Jika seseorang mengganti nama tidak terdefinisi, Anda akan berada dalam banyak masalah daripada hanya beberapa jika pemeriksaan gagal. Jika Anda benar-benar ingin melindungi kode Anda, bungkus dengan IFFE (ekspresi fungsi yang langsung dipanggil) seperti ini:

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

Jika Anda bekerja dengan variabel global (yang sudah salah) di lingkungan browser, saya akan memeriksa yang tidak terdefinisi seperti ini:

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

Karena variabel global adalah bagian dari objek jendela, Anda bisa mengecek terhadap undefined alih-alih casting ke string dan membandingkan string.

Selain itu, mengapa variabel Anda tidak didefinisikan? Saya telah melihat banyak kode di mana mereka memeriksa keberadaan variabel dan melakukan beberapa tindakan berdasarkan itu. Tidak sekali pun saya melihat di mana pendekatan ini benar.

Peeter
sumber
1
Validasi input dan pengecekan ketergantungan adalah alasan bagus untuk menggunakan ini. Jika saya memiliki file Javascript yang bergantung pada file lain yang telah memuat atau init objek yang telah dideklarasikan, maka akan berguna untuk menguji objek atau properti yang bergantung pada file yang tidak terdefinisi dan melemparkan pengecualian yang bagus alih-alih membiarkan skrip Anda gagal di suatu tempat yang tidak dapat diprediksi.
AmericanUmlaut
Kedengarannya seperti Anda mungkin perlu sesuatu dalam garis AMD (require.js)
Peeter
1
Atau saya mungkin hanya ingin melakukan perbandingan yang sangat sederhana daripada memasukkan perpustakaan lain dalam proyek saya :)
AmericanUmlaut
Terlambat untuk mengedit :(. Ingin menambahkan - require.js juga bukan solusi yang tepat untuk validasi input (objek init yang saya sebutkan di komentar awal saya). Jika Anda punya objek yang Anda harapkan akan diisi dengan tertentu nilai sebelum skrip dimuat, maka berguna untuk membuang pengecualian jika tidak ditentukan
AmericanUmlaut
1
Tidak, karena typeof mengembalikan string. Jadi typeof undefined return "undefined". window.input! == tidak terdefinisi (jika variabel Anda ada di global spoce)
Peeter
5

Jika Anda benar-benar khawatir tentang definisi ulang yang tidak didefinisikan, Anda dapat melindungi hal ini dengan beberapa metode pembantu seperti ini:

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

Ini berfungsi karena ketika seseorang menulis, undefined = "foo"dia hanya mengizinkan referensi nama undefined ke nilai baru, tetapi dia tidak mengubah nilai sebenarnya undefined.

Ivo Wetzel
sumber
1
Namun, kini Anda telah memperkenalkan panggilan fungsi, yang akan merusak kinerja.
Tim Down
Saya tidak berpikir bahwa pemanggilan fungsi ini akan mematikan kinerja, itu jauh lebih mungkin bahwa DOM akan menjadi hambatan. Tetapi bagaimanapun juga, jika Anda memiliki fungsi anonim besar yang biasa yang berisi pustaka Anda apa pun, Anda juga dapat menentukan undefined_checkdi bagian atas dan kemudian menggunakannya di mana-mana dalam kode Anda.
Ivo Wetzel
1
Setuju, dan saya tidak mengatakan ini adalah ide yang buruk. Hanya perlu menunjukkan bahwa memanggil fungsi ini akan melakukan lebih lambat daripada melakukan typeofpemeriksaan.
Tim Down
Saya pikir fungsi ini cukup sederhana sehingga akan diuraikan, sehingga kinerja tidak akan terpengaruh.
huyz
4
@TimDown: kode tulis pertama, itu bisa dibaca. kode tulis kedua, itu bisa dipertahankan, dan kemudian, jika benar-benar lambat. kemudian pikirkan tentang kinerja.
andreas
4

Anda juga dapat menggunakan operator void untuk mendapatkan nilai yang tidak ditentukan:

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

(Dan ya, seperti disebutkan dalam jawaban lain, ini akan menimbulkan kesalahan jika variabel tidak dideklarasikan, tetapi kasus ini sering dapat dikesampingkan dengan inspeksi kode, atau dengan kode refactoring, misalnya menggunakan window.input !== void 0untuk menguji variabel global atau menambahkan var input.)

Claude
sumber
1

Saya sebenarnya menemukan jika (typeof input !== 'undefined')dalam skenario ini digunakan untuk menyediakan parameter fungsi default:

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 menyediakan cara baru untuk memperkenalkan parameter fungsi default dengan cara ini:

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

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

Ini kurang verbose dan lebih bersih daripada opsi pertama.

JSpecs
sumber
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!

Avinash Maurya
sumber
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

Avinash Maurya
sumber
Bisakah Anda memberikan penjelasan?
jhpratt GOFUNDME RELICENSING
Ada enam nilai yang mungkin untuk mengetik pengembalian: objek, boolean, fungsi, angka, string, dan tidak terdefinisi. Typeof operator digunakan untuk mendapatkan tipe data (mengembalikan string) dari operandnya. Operand dapat berupa struktur literal atau data seperti variabel, fungsi, atau objek. Operator mengembalikan tipe data. Sintaks typeof operan atau typeof (operan)
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

Avinash Maurya
sumber
-7
if (input == undefined) { ... }

berfungsi dengan baik. Ini tentu saja bukan nullperbandingan, tetapi saya biasanya menemukan bahwa jika saya perlu membedakan antara undefineddan null, saya sebenarnya lebih perlu untuk membedakan antara undefineddan sembarang nilai salah, jadi

else if (input) { ... }

melakukannya.

Jika sebuah program meredefinisi, undefineditu benar-benar braindead.

Satu-satunya alasan saya bisa memikirkan adalah untuk kompatibilitas IE4, itu tidak memahami undefinedkata kunci (yang tidak benar-benar kata kunci, sayangnya), tapi tentu saja nilai-nilai bisa menjadi undefined , sehingga Anda harus memiliki ini:

var undefined;

dan perbandingan di atas akan bekerja dengan baik.

Dalam contoh kedua Anda, Anda mungkin membutuhkan tanda kurung ganda untuk membuat serat bahagia?

UniquePhoton
sumber
Anda input == undefinedakan kembali truepada nullinput.
mgol