variabel === undefined vs. typeof variabel === “undefined”

300

The jQuery Inti Style Pedoman menyarankan dua cara yang berbeda untuk memeriksa apakah suatu variabel didefinisikan.

  • Variabel Global: typeof variable === "undefined"
  • Variabel Lokal: variable === undefined
  • Properti: object.prop === undefined

Mengapa jQuery menggunakan satu pendekatan untuk variabel global dan lainnya untuk penduduk lokal dan properti?

Patrick McElhaney
sumber
Saya tidak bisa menjawab pertanyaan mengapa JQuery akan menggunakan kedua pendekatan, tetapi Javascript memang memiliki beberapa kebiasaan menarik yang berarti kedua hal ini agak berbeda. Seharusnya tidak masalah sebagian besar waktu (yaitu jika kode Anda waras), tetapi ada perbedaan namun: Lihat di sini untuk menulis - wtfjs.com/2010/02/15/undefined-is-mutable
Spudley
2
Seperti @Struppi tunjukkan, fungsi terluar jQuery memiliki argumen bernama undefined. Di dalam jQuery, foo === undefinedsedang memeriksa salinan lokal undefined bukan global (window.undefined), yang mungkin telah dimodifikasi oleh kode gila. Fakta bahwa undefined bisa berubah jelas layak dicatat dan saya senang Anda melakukannya. (+1)
Patrick McElhaney
1
Tautan saat ini untuk artikel itu adalah wtfjs.com/wtfs/2010-02-15-undefined-is-mutable
enigment

Jawaban:

366

Untuk variabel yang tidak dideklarasikan, typeof fooakan mengembalikan string literal "undefined", sedangkan pemeriksaan identitas foo === undefinedakan memicu kesalahan "foo tidak didefinisikan" .

Untuk variabel lokal (yang Anda ketahui dideklarasikan di suatu tempat), tidak ada kesalahan seperti itu akan terjadi, karenanya pemeriksaan identitas.

Linus Kleen
sumber
3
@ goreSplatter Anda tidak dapat menghapusnya sekarang. :-) Sulit untuk memilih, tetapi cara pertanyaannya diungkapkan, jawaban ini lebih cocok. Siapa pun yang tertarik pada bagaimana undefined bekerja secara umum (seperti saya) juga harus melihat jawaban lain, terutama @ Tim.
Patrick McElhaney
4
Saya akan menambahkan tanda kutip ( typeof foo; // -> "undefined") untuk menekankan itu adalah string dan bukan nilai primitif undefined.
c24w
117

Saya akan tetap menggunakan di typeof foo === "undefined"mana - mana. Itu tidak akan pernah salah.

Saya membayangkan alasan mengapa jQuery merekomendasikan dua metode yang berbeda adalah bahwa mereka mendefinisikan undefinedvariabel mereka sendiri di dalam fungsi tempat kode jQuery tinggal, jadi di dalam fungsi undefineditu aman dari gangguan dari luar. Saya juga akan membayangkan bahwa seseorang di suatu tempat telah membandingkan dua pendekatan yang berbeda dan menemukan bahwa foo === undefineditu lebih cepat dan karena itu memutuskan itulah cara untuk pergi. [PEMBARUAN: seperti disebutkan dalam komentar, perbandingan dengan undefinedjuga sedikit lebih pendek, yang bisa menjadi pertimbangan.] Namun, keuntungan dalam situasi praktis akan sama sekali tidak signifikan: pemeriksaan ini tidak akan pernah menjadi hambatan, dan apa Anda kalah adalah signifikan: mengevaluasi properti objek host untuk perbandingan dapat menimbulkan kesalahan sedangkan atypeof periksa tidak akan pernah.

Misalnya, berikut ini digunakan di IE untuk parsing XML:

var x = new ActiveXObject("Microsoft.XMLDOM");

Untuk memeriksa apakah ada loadXMLmetode yang aman:

typeof x.loadXML === "undefined"; // Returns false

Di samping itu:

x.loadXML === undefined; // Throws an error

MEMPERBARUI

Keuntungan lain dari typeofcek yang saya lupa sebutkan adalah bahwa ia juga bekerja dengan variabel yang tidak dideklarasikan, yang foo === undefinedtidak dicentang, dan sebenarnya melempar a ReferenceError. Terima kasih kepada @LinusKleen untuk mengingatkan saya. Sebagai contoh:

typeof someUndeclaredVariable; // "undefined"
someUndeclaredVariable === undefined; // throws a ReferenceError

Intinya: selalu gunakan typeofcek.

Tim Down
sumber
10
Terima kasih Tim. Poin Anda tentang kinerja masuk akal. Tim jQuery cenderung lebih peduli tentang dampak pada ukuran file. foo === undefined, ketika diminimalkan, mungkin sesuatu seperti f===u, sedangkan typeof foo === "undefined"hanya dapat dikurangi menjadi typeof f==="undefined".
Patrick McElhaney
1
Anda dapat mendefinisikan var u = "undefined"dan menguranginya menjadi typeof f==u, yang meningkatkan hal-hal tetapi masih lebih besar.
Tim Down
5
Poin bagus, tapi saya tidak yakin keamanan typeofterhadap variabel yang tidak dideklarasikan adalah keuntungan. Jika ada yang memungkinkan kesalahan pengetikan melewati lebih mudah, dan saya tidak bisa melihat kapan Anda sebenarnya ingin memeriksa jenis variabel yang tidak dideklarasikan.
David Tang
2
@ Box9: Saya bisa membayangkan menggunakannya di perpustakaan untuk memeriksa keberadaan perpustakaan lain.
Tim Down
2
@jontro: Itu salah satu alasan untuk tidak menggunakan JSLint.
Tim Down
29

Namun alasan lain untuk menggunakan varian typeof: undefineddapat didefinisikan ulang.

undefined = "foo";
var variable = "foo";
if (variable === undefined)
  console.log("eh, what?!");

Hasil dari typeof variable tidak bisa.

Pembaruan : perhatikan bahwa ini bukan kasus di ES5 di mana global undefinedadalah properti yang tidak dapat dikonfigurasi, tidak dapat ditulis:

15.1.1 Nilai Properti Objek Global
[...]
15.1.1.3 undefined
Nilai undefinedtidak terdefinisi (lihat 8.1). Properti ini memiliki atribut
{[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}.

Tapi itu masih bisa dibayangi oleh variabel lokal:

(function() {
  var undefined = "foo";
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})()

atau parameter:

(function(undefined) {
  var variable = "foo";
  if (variable === undefined)
    console.log("eh, what?!");  
})("foo")
Jakob
sumber
17
Tidak dapat didefinisikan ulang dalam ES5.
Ry-
6
undefinedProperti global tidak dapat didefinisikan ulang dalam ES5, tetapi masih dapat dibayangi dengan variabel lokal. void 0lebih pendek dan lebih aman.
Oriol
7

Karena undefinedtidak selalu dideklarasikan, tetapi jQuery menyatakan undefineddalam fungsi utamanya. Jadi mereka menggunakan nilai aman secara undefinedinternal, tetapi di luar, mereka menggunakan typeofgaya untuk menjadi aman.

Struppi
sumber
1

Untuk variabel lokal, pemeriksaan dengan localVar === undefinedakan berfungsi karena mereka harus didefinisikan di suatu tempat dalam lingkup lokal atau mereka tidak akan dianggap lokal.

Untuk variabel yang tidak lokal dan tidak didefinisikan di mana saja, pemeriksaan someVar === undefinedakan membuang pengecualian: Uncaught ReferenceError: j tidak didefinisikan

Berikut adalah beberapa kode yang akan menjelaskan apa yang saya katakan di atas. Harap perhatikan komentar sebaris untuk kejelasan lebih lanjut .

function f (x) {
    if (x === undefined) console.log('x is undefined [x === undefined].');
    else console.log('x is not undefined [x === undefined.]');

    if (typeof(x) === 'undefined') console.log('x is undefined [typeof(x) === \'undefined\'].');
    else console.log('x is not undefined [typeof(x) === \'undefined\'].');

    // This will throw exception because what the hell is j? It is nowhere to be found.
    try
    {
        if (j === undefined) console.log('j is undefined [j === undefined].');
        else console.log('j is not undefined [j === undefined].');
    }
    catch(e){console.log('Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.');}

    // However this will not throw exception
    if (typeof j === 'undefined') console.log('j is undefined (typeof(x) === \'undefined\'). We can use this check even though j is nowhere to be found in our source code and it will not throw.');
    else console.log('j is not undefined [typeof(x) === \'undefined\'].');
};

Jika kita memanggil kode di atas seperti ini:

f();

Outputnya akan seperti ini:

x is undefined [x === undefined].
x is undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Jika kita memanggil kode di atas seperti ini (dengan nilai sebenarnya):

f(null); 
f(1);

Outputnya adalah:

x is not undefined [x === undefined].
x is not undefined [typeof(x) === 'undefined'].
Error!!! Cannot use [j === undefined] because j is nowhere to be found in our source code.
j is undefined (typeof(x) === 'undefined'). We can use this check even though j is nowhere to be found in our source code and it will not throw.

Ketika Anda melakukan pemeriksaan seperti ini:, typeof x === 'undefined'Anda pada dasarnya menanyakan ini: Harap periksa apakah variabel xada (telah ditentukan) di suatu tempat dalam kode sumber. (lebih atau kurang). Jika Anda tahu C # atau Java, jenis pemeriksaan ini tidak pernah dilakukan karena jika tidak ada, itu tidak akan dikompilasi.

<== Fiddle Me ==>

CodingYoshi
sumber
1

Ringkasan:

Ketika di lingkup global kita sebenarnya ingin mengembalikan true jika variabel tidak dideklarasikan atau memiliki nilai undefined:

var globalVar1;

// This variable is declared, but not defined and thus has the value undefined
console.log(globalVar1 === undefined);

// This variable is not declared and thus will throw a referenceError
console.log(globalVar2 === undefined);

Karena dalam lingkup global kami tidak 100% yakin jika suatu variabel dideklarasikan, ini mungkin memberi kami ReferenceError. Ketika kami menggunakan typeofoperator pada variabel yang tidak dikenal, kami tidak mendapatkan masalah ini ketika variabel tidak dideklarasikan:

var globalVar1;

console.log(typeof globalVar1 === 'undefined');
console.log(typeof globalVar2 === 'undefined');

Ini disebabkan oleh fakta bahwa typeofoperator mengembalikan string undefinedketika suatu variabel tidak dideklarasikan atau saat ini memegang nilai undefinedyang persis seperti yang kita inginkan.


  • Dengan variabel lokal kami tidak memiliki masalah ini karena kami tahu sebelumnya bahwa variabel ini akan ada. Kami hanya dapat melihat fungsi masing-masing jika variabel hadir.
  • Dengan properti objek, kami tidak memiliki masalah ini karena ketika kami mencoba mencari properti objek yang tidak ada, kami juga mendapatkan nilai undefined

var obj = {};

console.log(obj.myProp === undefined);

Willem van der Veen
sumber
-5

typeof a === 'undefined'lebih cepat maka a === 'undefined'sekitar 2 kali pada node v6.9.1.

Eduard Popov
sumber
3
Itu bukan hal yang sama yang Anda ketikkan. Saya pikir maksud Anda undefinedpada bagian kedua, bukan'undefined'
scaryguy