Pertanyaan Mendeteksi properti objek yang tidak terdefinisi


Apa cara terbaik untuk memeriksa apakah properti objek dalam JavaScript tidak terdefinisi?


2430
2017-08-26 07:25


asal


Jawaban:


Menggunakan:

if (typeof something === "undefined") {
    alert("something is undefined");
}

Jika suatu variabel objek yang memiliki beberapa properti Anda dapat menggunakan hal yang sama seperti ini:

if (typeof my_obj.someproperties === "undefined"){
    console.log('the property is not available...'); // print into console
}

Sejak ECMAScript 5, undefined tidak dapat ditimpa, jadi my_obj === undefined akan bekerja juga, tetapi hanya jika my_obj ada. Ini mungkin atau mungkin tidak diinginkan karena Anda juga dapat menggunakannya null jika Anda membutuhkan semantik ini (lihat Apa perbedaan antara nol dan tidak didefinisikan dalam JavaScript?). Untuk properti objek, ia bekerja terlepas dari apakah properti itu ada.


2316
2018-01-06 12:27



Saya yakin ada sejumlah jawaban yang salah untuk topik ini. Bertentangan dengan kepercayaan umum, "tidak terdefinisi" adalah tidak kata kunci dalam JavaScript dan sebenarnya dapat memiliki nilai yang ditetapkan untuk itu.

Kode yang benar

Cara paling ampuh untuk melakukan tes ini adalah:

if (typeof myVar === "undefined")

Ini akan selalu mengembalikan hasil yang benar, dan bahkan menangani situasi di mana myVar tidak dideklarasikan.

Kode degenerasi. JANGAN GUNAKAN.

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

Selain itu, myVar === undefined akan meningkatkan kesalahan dalam situasi di mana myVar tidak dideklarasikan.


803
2017-08-23 18:03



Di JavaScript ada batal dan ada tidak terdefinisi. Mereka memiliki arti yang berbeda.

  • tidak terdefinisi berarti bahwa nilai variabel belum ditentukan; tidak diketahui berapa nilainya.
  • batal Berarti bahwa nilai variabel didefinisikan dan diatur ke null (tidak memiliki nilai).

Marijn Haverbeke menyatakan, dalam bukunya yang gratis, "JavaScript Keren"(Penekanan saya):

Ada juga nilai yang serupa, null, yang artinya 'nilai ini didefinisikan, tetapi tidak memiliki nilai'. Perbedaan makna antara tidak terdefinisi dan nol sebagian besar bersifat akademis, dan biasanya tidak terlalu menarik. Dalam program praktis, seringkali perlu untuk memeriksa apakah sesuatu 'memiliki nilai'. Dalam kasus ini, ekspresi sesuatu == tidak terdefinisi dapat digunakan, karena, meskipun mereka tidak persis nilai yang sama, null == tidak terdefinisi akan menghasilkan true.

Jadi, saya kira cara terbaik untuk memeriksa apakah sesuatu tidak terdefinisi adalah:

if (something == undefined)

Semoga ini membantu!

Edit: Sebagai tanggapan atas hasil edit Anda, properti objek harus bekerja dengan cara yang sama.

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

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

133
2017-08-26 07:36



Meskipun sangat disarankan oleh banyak jawaban lainnya di sini, typeof  adalah pilihan yang buruk. Seharusnya tidak pernah digunakan untuk memeriksa apakah variabel memiliki nilai undefined, karena berfungsi sebagai pemeriksaan gabungan untuk nilai undefined dan apakah ada variabel. Dalam sebagian besar kasus, Anda tahu kapan suatu variabel ada, dan typeof hanya akan memperkenalkan potensi kegagalan senyap jika Anda salah ketik dalam nama variabel atau dalam string literal '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!
}

Jadi kecuali Anda melakukan deteksi fitur², di mana ada ketidakpastian apakah nama yang diberikan akan berada dalam lingkup (seperti memeriksa typeof module !== 'undefined' sebagai langkah dalam kode khusus untuk lingkungan CommonJS), typeof adalah pilihan yang berbahaya ketika digunakan pada variabel, dan opsi yang benar adalah membandingkan nilai secara langsung:

var foo = …;

if (foo === undefined) {
    ⋮
}

Beberapa kesalahpahaman umum tentang hal ini termasuk:

  • bahwa membaca variabel "terinisialisasi" (var foo) atau parameter (function bar(foo) { … }, disebut sebagai bar()) akan gagal. Ini tidak benar - variabel tanpa inisialisasi eksplisit dan parameter yang tidak diberikan nilai selalu menjadi undefined, dan selalu dalam lingkup.

  • bahwa undefined dapat ditimpa. Ada banyak lagi hal ini. undefined bukan kata kunci dalam JavaScript. Sebaliknya, ini adalah properti pada objek global dengan nilai Undefined. Namun, sejak ES5, properti ini telah hanya-baca dan tidak dapat dikonfigurasi. Tidak ada peramban modern yang akan mengizinkan undefined properti harus diubah, dan pada 2017 ini telah terjadi untuk waktu yang lama. Kekurangan mode ketat tidak memengaruhi undefined'S perilaku baik - itu hanya membuat pernyataan suka undefined = 5 jangan melakukan apa pun daripada melempar. Karena itu bukan kata kunci, Anda bisa menyatakan variabel dengan nama undefined, dan variabel-variabel itu dapat diubah, membuat pola umum ini:

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

    lebih berbahaya daripada menggunakan global undefined. Jika Anda harus kompatibel dengan ES3, ganti undefined dengan void 0 - tidak suka typeof. (void selalu menjadi operator unary yang mengevaluasi ke nilai Undefined untuk operan apa pun.)

Dengan cara variabel bekerja, saatnya untuk menjawab pertanyaan sebenarnya: properti objek. Tidak ada alasan untuk digunakan typeof untuk properti objek. Pengecualian sebelumnya terkait deteksi fitur tidak berlaku di sini - typeof hanya memiliki perilaku khusus pada variabel, dan ekspresi bahwa properti objek referensi bukan variabel.

Ini:

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

aku s selalu persis setara untuk ini³:

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

dan dengan mempertimbangkan saran di atas, untuk menghindari kebingungan pembaca mengapa Anda menggunakan typeof, karena paling masuk akal untuk digunakan === untuk memeriksa kesetaraan, karena itu bisa direfaktorkan untuk memeriksa nilai variabel nanti, dan karena itu terlihat jelas lebih baik, Anda harus selalu menggunakan === undefined³ di sini juga.

Hal lain yang perlu dipertimbangkan ketika datang ke properti objek adalah apakah Anda benar-benar ingin memeriksanya undefined sama sekali. Sebuah nama properti yang diberikan dapat absen pada objek (menghasilkan nilai undefined saat membaca), hadir pada objek itu sendiri dengan nilai undefined, sajikan pada prototipe objek dengan nilainya undefined, atau hadir pada salah satu dari mereka yang tidakundefined nilai. 'key' in obj akan memberi tahu Anda apakah kunci ada di mana saja pada rantai prototipe objek, dan Object.prototype.hasOwnProperty.call(obj, 'key') akan memberi tahu Anda apakah itu langsung pada objek. Saya tidak akan membahas lebih rinci dalam jawaban ini tentang prototipe dan menggunakan objek sebagai peta string-key, karena itu sebagian besar ditujukan untuk melawan semua saran buruk dalam jawaban lain terlepas dari interpretasi yang mungkin dari pertanyaan asli. Baca terus prototipe objek di MDN untuk lebih!

¹ pilihan nama variabel contoh yang tidak biasa? ini adalah kode mati nyata dari ekstensi NoScript untuk Firefox.
² jangan berasumsi bahwa tidak mengetahui apa yang ada di ruang lingkup tidak apa-apa pada umumnya. Kerentanan bonus yang disebabkan oleh penyalahgunaan lingkup dinamis: Project Zero 1225
³ sekali lagi dengan asumsi lingkungan ES5 + dan itu undefined mengacu kepada undefined milik objek global. pengganti void 0 jika tidak.


130
2018-02-26 21:17



Apa artinya ini: "properti objek tidak terdefinisi"?

Sebenarnya ini bisa berarti dua hal yang sangat berbeda! Pertama, itu bisa berarti properti yang belum pernah ditetapkan dalam objek dan, kedua, itu bisa berarti properti yang memiliki nilai tidak terdefinisi. Mari kita lihat kode ini:

var o = { a: undefined }

Aku s o.a tidak terdefinisi? Iya nih! Nilainya tidak terdefinisi. Aku s o.b tidak terdefinisi? Yakin! Tidak ada properti 'b' sama sekali! OK, lihat sekarang bagaimana pendekatan yang berbeda berperilaku dalam kedua situasi:

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

Kami dapat dengan jelas melihat itu typeof obj.prop == 'undefined' dan obj.prop === undefined setara, dan mereka tidak membedakan situasi yang berbeda. Dan 'prop' in obj dapat mendeteksi situasi ketika properti belum didefinisikan sama sekali dan tidak memperhatikan nilai properti yang mungkin tidak terdefinisi.

Jadi apa yang harus dilakukan?

1) Anda ingin tahu apakah suatu properti tidak ditentukan oleh makna pertama atau kedua (situasi yang paling umum).

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

2) Anda hanya ingin tahu apakah objek memiliki beberapa properti dan tidak peduli dengan nilainya.

'prop' in obj

Catatan:

  • Anda tidak dapat memeriksa objek dan propertinya pada saat yang bersamaan. Misalnya, ini x.a === undefined atau ini typeof x.a == 'undefined' menimbulkan ReferenceError: x is not defined jika x tidak didefinisikan.
  • Variabel undefined adalah variabel global (jadi sebenarnya window.undefined di browser). Ini telah didukung sejak ECMAScript 1st Edition dan sejak ECMAScript 5 itu hanya baca. Jadi di browser modern tidak mungkin didefinisi ulang menjadi true karena banyak penulis suka menakut-nakuti kami, tetapi ini masih berlaku untuk peramban yang lebih lama.

Perjuangan terakhir: obj.prop === undefined vs typeof obj.prop == 'undefined'

Plus dari obj.prop === undefined:

  • Ini sedikit lebih pendek dan terlihat sedikit lebih cantik
  • Mesin JavaScript akan memberi Anda kesalahan jika Anda salah mengeja undefined

Minus dari obj.prop === undefined:

  • undefined dapat ditimpa di browser lama

Plus dari typeof obj.prop == 'undefined':

  • Itu benar-benar universal! Ia bekerja di browser baru dan lama.

Minus dari typeof obj.prop == 'undefined':

  • 'undefned' (salah eja) di sini hanya string konstan, jadi mesin JavaScript tidak dapat membantu Anda jika Anda salah eja seperti yang baru saja saya lakukan.

Perbarui (untuk JavaScript sisi server):

Node.js mendukung variabel global undefined sebagai global.undefined (Ini juga dapat digunakan tanpa awalan 'global'). Saya tidak tahu tentang implementasi lain dari JavaScript sisi server.


100
2017-08-08 20:28



Masalah ini bermuara pada tiga kasus:

  1. Objek memiliki properti dan nilainya tidak undefined.
  2. Objek memiliki properti dan nilainya undefined.
  3. Objek tidak memiliki properti.

Ini memberi tahu kita sesuatu yang saya anggap penting:

Ada perbedaan antara anggota yang tidak terdefinisi dan anggota yang ditentukan dengan nilai tidak terdefinisi.

Tapi sayangnya typeof obj.foo tidak memberi tahu kami mana dari tiga kasus yang kami miliki. Namun kita bisa menggabungkan ini dengan "foo" in objuntuk membedakan kasusnya.

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

Perlu dicatat bahwa tes ini sama null entri juga

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

Saya berpendapat bahwa dalam beberapa kasus lebih masuk akal (dan lebih jelas) untuk memeriksa apakah properti ada di sana, daripada memeriksa apakah itu tidak terdefinisi, dan satu-satunya kasus di mana cek ini akan berbeda adalah kasus 2, kasus langka entri yang sebenarnya di objek dengan nilai tidak terdefinisi.

Sebagai contoh: Saya baru saja refactoring sekelompok kode yang memiliki banyak cek apakah suatu benda memiliki properti tertentu.

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

Yang lebih jelas ketika ditulis tanpa cek untuk tidak terdefinisi.

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

Tetapi seperti yang telah disebutkan ini tidak persis sama (tetapi lebih dari cukup baik untuk kebutuhan saya).


59
2018-06-08 04:04



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

Ini berhasil bagi saya sementara yang lain tidak.


38
2017-07-27 16:03



Saya tidak yakin darimana asal penggunaan === dengan typeof datang dari, dan sebagai konvensi saya melihatnya digunakan di banyak perpustakaan, tetapi operator typeof mengembalikan string literal, dan kami tahu bahwa di depan, jadi mengapa Anda juga ingin mengetik cek juga?

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

33
2017-09-22 14:20



Crossposting saya menjawab dari pertanyaan terkait Bagaimana cara memeriksa "tidak terdefinisi" di JavaScript?

Khusus untuk pertanyaan ini, lihat kasus uji dengan someObject.<whatever>.


Beberapa skenario yang mengilustrasikan hasil dari berbagai jawaban: http://jsfiddle.net/drzaus/UVjM4/

(Perhatikan bahwa penggunaan var untuk in tes membuat perbedaan ketika dalam pembungkus scoped)

Kode untuk referensi:

(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;
    }
})();

Dan hasilnya:

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

19
2018-01-13 17:43



Jika kamu melakukan

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

itu akan gagal ketika variabel myvar tidak ada, karena myvar tidak didefinisikan, sehingga skripnya rusak dan pengujian tidak berpengaruh.

Karena objek window memiliki lingkup global (objek default) di luar fungsi, deklarasi akan 'dilampirkan' ke objek window.

Sebagai contoh:

var myvar = 'test';

Variabel global myvar sama dengan window.myvar atau jendela ['myvar']

Untuk menghindari kesalahan untuk menguji ketika ada variabel global, Anda sebaiknya menggunakan:

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

Pertanyaannya jika suatu variabel benar-benar ada tidak masalah, nilainya tidak benar. Jika tidak, itu konyol untuk menginisialisasi variabel dengan tidak terdefinisi, dan lebih baik menggunakan nilai palsu untuk menginisialisasi. Ketika Anda tahu bahwa semua variabel yang Anda nyatakan diinisialisasi dengan false, Anda cukup memeriksa jenisnya atau mengandalkan !window.myvar untuk memeriksa apakah itu memiliki nilai yang benar / valid. Jadi, bahkan ketika variabel tidak didefinisikan kemudian !window.myvar sama untuk myvar = undefined atau myvar = false atau myvar = 0.

Ketika Anda mengharapkan tipe tertentu, uji jenis variabel. Untuk mempercepat pengujian kondisi yang sebaiknya Anda lakukan:

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

Ketika kondisi pertama dan sederhana benar, interpreter melompati tes berikutnya.

Itu selalu lebih baik untuk menggunakan contoh / objek dari variabel untuk memeriksa apakah itu mendapat nilai yang valid. Ini lebih stabil dan merupakan cara pemrograman yang lebih baik.

(y)


14
2017-08-12 14:40



Saya tidak melihat (harap saya tidak melewatkannya) siapa pun yang memeriksa objek sebelum properti. Jadi, ini adalah yang terpendek dan paling efektif (walau belum tentu yang paling jelas):

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

Jika obj atau obj.prop tidak terdefinisi, null, atau "falsy", pernyataan if tidak akan mengeksekusi blok kode. Ini adalah biasanya perilaku yang diinginkan dalam sebagian besar pernyataan blok kode (dalam JavaScript).


13
2017-09-25 18:41