Mengapa ada nilai `null` di JavaScript?

116

Di JavaScript, ada dua nilai yang pada dasarnya mengatakan 'Saya tidak ada' - undefineddan null.

Properti yang belum ditetapkan apa pun oleh programmer undefined, tetapi agar properti menjadi null, nullharus ditetapkan secara eksplisit padanya.

Saya pernah berpikir bahwa ada kebutuhan nullkarena undefinedadalah nilai primitif dan nullsebuah objek. Ini tidak, bahkan jika typeof nullakan menghasilkan 'object': Sebenarnya, keduanya nilai-nilai primitif - yang berarti tidak undefinedatau nulldapat kembali dari fungsi konstruktor, karena keduanya akan dikonversi ke obyek kosong (kita harus melempar kesalahan kegagalan kabarkan di konstruktor).

Keduanya juga mengevaluasi falsedalam konteks boolean. Satu-satunya perbedaan nyata yang dapat saya pikirkan adalah bahwa yang satu mengevaluasi NaN, yang lain ke 0dalam konteks numerik.

Jadi mengapa ada keduanya undefineddan nulljika ini hanya membingungkan pemrogram yang salah memeriksa nullsaat mencoba mencari tahu apakah properti telah disetel atau belum?

Yang ingin saya ketahui adalah jika ada yang memiliki contoh yang masuk akal di mana perlu menggunakan nullyang tidak bisa diekspresikan menggunakan undefined.

Jadi konsensus umum tampaknya undefinedberarti 'tidak ada properti seperti itu' sedangkan nullberarti 'properti itu ada, tetapi tidak memiliki nilai'.

Saya dapat menerimanya jika implementasi JavaScript benar-benar akan memberlakukan perilaku ini - tetapi undefinedmerupakan nilai primitif yang benar-benar valid, sehingga dapat dengan mudah ditetapkan ke properti yang ada untuk memutuskan kontrak ini. Oleh karena itu, jika Anda ingin memastikan apakah suatu properti ada, Anda harus menggunakan inoperator atau hasOwnProperty()tetap. Jadi sekali lagi: apa kegunaan praktis dari nilai terpisah untuk undefineddan null?

Saya benar-benar menggunakan undefinedsaat saya ingin menghapus nilai properti yang tidak lagi digunakan tetapi saya tidak mau delete. Haruskah saya gunakan nullsebagai gantinya?

Christoph
sumber
3
Untuk menjawab pertanyaan terakhir Anda: Tidak, Anda tidak boleh menyetel properti ke undefined.
Shog9
4
"undefined" hanyalah sebuah variabel dalam lingkup global dengan nilai primitif "undefined". Dimungkinkan untuk menentukan nilai lain ke variabel: {undefined = "Hello"; alert (undefined);} Cara yang lebih dapat diandalkan untuk menguji undefined: {if (typeof myvar === "undefined") alert ("undefined")}
sekitar
1
Lihat bagian 4.3.9 - 12 di ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf untuk undefined / null, dan 15.1.1.3 untuk variabel "undefined" dalam lingkup global.
sekitar
1
Anda harus menghapus sebuah objek atau menyetelnya ke null jika itu lebih masuk akal, tetapi tidak untuk undefined.
sekitar
4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.Tidak, hanya undefinedkatakan itu.
Balapan Ringan di Orbit

Jawaban:

78

Pertanyaannya sebenarnya bukan "mengapa ada nilai null di JS" - ada nilai null di sebagian besar bahasa dan umumnya dianggap sangat berguna.

Pertanyaannya adalah, "mengapa ada nilai yang tidak ditentukan di JS". Tempat utama di mana itu digunakan:

  1. ketika Anda mendeklarasikan var x;tetapi tidak menetapkannya, xmemegang tidak terdefinisi;
  2. ketika fungsi Anda mendapatkan lebih sedikit argumen daripada yang dideklarasikan;
  3. ketika Anda mengakses properti objek yang tidak ada.

nullpasti akan berhasil dengan baik untuk (1) dan (2) *. (3) harus benar-benar membuang pengecualian segera, dan fakta bahwa itu tidak, alih-alih mengembalikan keanehan ini undefinedyang akan gagal nanti, adalah sumber besar kesulitan debugging.

*: Anda juga bisa berargumen bahwa (2) harus menampilkan pengecualian, tetapi kemudian Anda harus menyediakan mekanisme yang lebih baik dan lebih eksplisit untuk argumen default / variabel.

Namun JavaScript awalnya tidak memiliki pengecualian, atau cara apa pun untuk menanyakan suatu objek apakah itu memiliki anggota dengan nama tertentu - satu-satunya cara adalah (dan terkadang masih) mengakses anggota dan melihat apa yang Anda dapatkan. Mengingat bahwa nullsudah memiliki tujuan dan Anda mungkin ingin menetapkan anggota untuk itu, diperlukan nilai out-of-band yang berbeda. Jadi kami punya undefined, itu bermasalah seperti yang Anda tunjukkan, dan itu adalah 'fitur' JavaScript hebat lainnya yang tidak akan pernah bisa kami singkirkan.

Saya sebenarnya menggunakan undefined ketika saya ingin menghapus nilai properti yang tidak lagi digunakan tetapi tidak ingin saya hapus. Haruskah saya menggunakan null sebagai gantinya?

Iya. Simpan undefinedsebagai nilai khusus untuk memberi isyarat ketika bahasa lain mungkin mengeluarkan pengecualian.

nullumumnya lebih baik, kecuali pada beberapa antarmuka DOM IE di mana pengaturan sesuatu nulldapat menghasilkan kesalahan. Seringkali dalam kasus ini pengaturan ke string kosong cenderung berhasil.

bobince
sumber
10
Arg dapat diperluas. Anda dapat mampir sebanyak yang Anda suka dan suatu fungsi berpotensi mengulang dan memanfaatkan semuanya. Objek dapat diberi properti baru kapan saja. Keduanya adalah fitur yang kuat tetapi saya menduga memiliki pengecualian yang dilemparkan seperti yang Anda inginkan akan menjadi banyak overhead. IMO, itu sepadan dengan pengorbanannya. Saya menghabiskan lebih sedikit waktu untuk memeriksa keberadaan di JS daripada biasanya saya melakukan casting dalam paradigma bahasa yang lebih ketat.
Erik Reppen
Lucu bagaimana jawaban yang diterima untuk sebuah pertanyaan dimulai dengan "ini bukan pertanyaannya ..."
Phillip
@bobince apakah versi awal JS tidak memiliki inoperator atau hasOwnProperty? Karena mereka jauh lebih aman daripada obj.hello !== undefinedmemeriksa apakah suatu properti ada pada suatu objek.
Andy
Tidak masalah, saya menjawab pertanyaan saya sendiri. Menurut MDN, keduanya diperkenalkan di ES3.
Andy
37

Paling baik dijelaskan di sini , tetapi secara ringkas:

undefined adalah ketiadaan tipe dan nilai, dan null adalah ketiadaan nilai.

Selain itu, jika Anda melakukan perbandingan '==' sederhana, Anda benar, hasilnya sama saja. Tapi coba ===, yang membandingkan tipe dan nilai, dan Anda akan melihat perbedaannya.

Eddie Parker
sumber
1
Saya tahu itu null !== undefined- pertanyaan saya adalah mengapa ada kebutuhan akan dua hal yang mengekspresikan konsep semantik yang sama; juga, tautan Anda menyebutkan bahwa 'null adalah sebuah objek' - itu salah, itu primitif ...
Christoph
2
Mereka bukanlah konsep semantik yang sama. Bagi saya setidaknya, ada perbedaan yang signifikan antara properti yang diberi nilai null, dan properti yang tidak ada.
Daniel Schaffer
Tapi hanya itu, mereka bukanlah konsep semantik yang sama. Null akan dipaksa saat menggunakan == untuk menyiratkan hal yang sama, sebagai kemudahan bagi programmer.
Eddie Parker
1
@EricElliott: typeofkebohongan - baca spesifikasi atau coba kembali nulldari konstruktor
Christoph
5
@EricElliott: nilai kembalian konstruktor tidak ada hubungannya dengan falsy-ness, tetapi dengan object-ness: jika nilai yang dikembalikan adalah sebuah objek, kembalikan itu; jika itu primitif seperti nullatau 42, buang nilai kembalian dan kembalikan objek yang baru dibuat sebagai gantinya
Christoph
17

Saya rasa tidak ada alasan untuk memiliki keduanya nulldan undefined, karena satu-satunya alasan yang disarankan banyak orang (" undefinedberarti tidak ada variabel / properti seperti itu") tidak valid, setidaknya di JavaScript. undefinedtidak dapat memberi tahu Anda apakah variabel / properti ada atau tidak.

console.log(foo);               // "ReferenceError: foo is not defined"
                                // foo does not exist
var foo;
console.log(foo);               // "undefined", a different response
console.log(foo === undefined); // "true", but it does exist

var obj = {};
console.log(obj.hasOwnProperty("foo")); // "false", no such property
obj.foo = undefined;
console.log(obj.hasOwnProperty("foo")); // "true", it exists and has the value "undefined"
console.log(obj.foo === undefined);     // "true", but it does exist

obj.bar = "delete me";
obj.bar = undefined;
console.log(obj.hasOwnProperty("bar")); // "true", not actually deleted
delete obj.bar;
console.log(obj.hasOwnProperty("bar")); // "false", deleted

Seperti yang Anda lihat, pemeriksaan foo === undefinedtidak memberi tahu Anda apakah fooada, dan pengaturan obj.bar = undefinedtidak benar-benar dihapus bar.

Mungkin maksud asli penulis JavaScript yang undefinedharus mewakili "tidak ada". Namun, implementasinya ternyata tidak seperti itu.

Lei Zhao
sumber
1
Ganti undefineddengan nulldalam contoh kode Anda di atas, dan semua tanggapannya sama. Saya tidak yakin bagaimana ini menjawab pertanyaan itu. Apakah ini dimaksudkan sebagai komentar atas jawaban orang lain?
Eric Elliott
1
@EricElliott Jawaban saya untuk pertanyaan ini adalah tidak ada alasan untuk memiliki keduanya nulldan undefined, karena satu-satunya alasan yang disarankan banyak orang adalah tidak valid.
Lei Zhao
Anda harus mengedit jawaban Anda dan benar-benar mengatakannya. Saya mungkin akan memberi suara positif jika Anda memberikan jawaban itu. =)
Eric Elliott
@EllEllott Saya pikir Anda benar. Saya telah mengedit jawaban saya. Terima kasih!
Lei Zhao
3
Contoh ini sebenarnya menunjukkan bahwa jika Anda tidak menetapkan variabel, ia akan kembali undefined. Tetapi jika Anda benar-benar menugaskannya undefined, itu tidak benar undefined- benar - itu didefinisikan dengan undefineddan memiliki referensi padanya. Satu-satunya perbedaan antara undefineddan nulladalah penggunaan dan tujuan historisnya. Keduanya atom.
Aleksej Komarov
6

Sangat mungkin untuk membutuhkan keduanya. Misalnya jika Anda query WMI sangat mungkin untuk memiliki properti kelas kembali yang memiliki nilai null. Mereka didefinisikan, mereka kebetulan memegang nol pada saat itu.

EBGreen
sumber
6

Saya pikir kesimpulan Anda bahwa JavaScript mendefinisikan undefinedsebagai "tidak ada properti seperti itu" dan nullsebagai "properti tidak memiliki nilai" adalah benar. Dan dalam bahasa yang dinamis seperti JavaScript, ini adalah perbedaan yang sangat penting. Penggunaan kata bebek berarti kita harus mampu membedakan antara properti yang tidak ada dan yang tidak bernilai. Ini adalah cara utama kami untuk memperoleh informasi tipe. dalam bahasa yang diketik secara statis, ada perbedaan yang pasti antara bidang menjadi nol dan bidang tidak ada. Dalam JavaScript hal ini tidak berbeda. Namun itu diperiksa pada waktu proses, dan dapat dimodifikasi hingga saat itu.

Saya harus setuju bahwa penerapannya aneh karena sering kali perbedaannya kabur. Namun menurut saya perbedaan itu penting dalam JavaScript. Dan kemampuan untuk menugaskan undefineditu penting.

Saya ingat pernah membaca posting blog beberapa waktu lalu tentang RPG online yang ditulis dalam JavaScript. Ini menggunakan contoh di mana objek dibuat sebagai salinan dari instance yang ada daripada prototipe (kelas, fungsi, apa pun), dan kemudian diubah. Ini benar-benar membuat saya memahami betapa hebatnya hal undefineditu saat memodifikasi objek yang ada, tetapi saya tidak dapat mengingat siapa yang menulisnya.

Jack Ryan
sumber
Bisakah Anda membagikan RPG ini?
Michael
3

Secara semantik mereka memiliki arti yang berbeda. Jenis null memiliki tepat satu nilai dalam domainnya, null dan properti dapat diberi nilai khusus ini. Tidak terdefinisi menunjukkan kurangnya nilai yang telah ditetapkan.

AnthonyWJones
sumber
1
tetapi Anda dapat menggunakan dengan undefinedbaik untuk menetapkan ke properti, jadi kontrak ini (hanya dikembalikan undfinedjika tidak ada properti seperti itu) dapat dengan mudah diputuskan oleh programmer ...
Christoph
2
Anda bisa , tetapi Anda pasti tidak boleh. Undefined digunakan sebagai bentuk pengecualian yang sangat dasar / sederhana dalam JavaScript - jangan gunakan itu sebagai nilai dan tetapkan ke beberapa properti! Itu orang gila.
rfunduk
3

Sebagai programmer Java, saya melihat perbedaan besar antara undefined dan null. Coding JavaScript, jangan terlalu banyak, karena JavaScript tidak diketik dengan kuat, dan perbedaan antara undefined dan null dikaburkan oleh konversi otomatis yang sering dilakukan oleh run-time. BTW, saya sering memanfaatkan konversi tersebut; mereka membuat kode JS saya lebih ringkas dan mudah dibaca.

Untuk menjawab pertanyaan Anda, undefined berarti nilai tidak pernah ditetapkan. Secara praktis, ini umumnya mengarah ke bug. Jika yourObject.property tidak ditentukan, itu berarti Anda tidak menyetel properti karena suatu alasan, atau saya mencari sesuatu yang tidak ada sama sekali. Ini adalah masalah nyata saat mengerjakan proyek dengan lebih dari satu pembuat kode.

null berarti "tidak ada nilai" yang ditetapkan secara eksplisit. Secara praktis, Anda memberi tahu saya sesuatu tentang properti, mungkin yang tidak digunakan dalam konteks ini, atau nilai belum ditentukan.

Di Java, upaya untuk mengakses bidang yang tidak ditentukan akan selalu menghasilkan pengecualian. Nyatanya, kompilator dapat dibuat untuk memperingatkan Anda tentang hal ini dalam kode Anda.

Steve11235
sumber
0

Coba contoh ini:

<html>
<head>
    <script type="text/javascript">
        function ShowObjProperties(obj) {
            var property, propCollection = "";

            for(property in obj) {
                propCollection += (property + ": " + obj[property] + "\n");
            }

            alert(propCollection);
        }

        var obj = {
            userid: 3,
            name: 'me!',
            speak: function() { alert('Hi! My name is ' + this.name + ' and my ID is ' + this.userid + '.'); }
        }

        //Shows all properties
        ShowObjProperties(obj);

        //The Speak function is no longer in the list!
        delete obj.speak;
        alert(typeof obj.speak);
        ShowObjProperties(obj);

        //The UserID is still listed, it just has no value!
        obj.userid = null;
        ShowObjProperties(obj);
    </script>
</head>
<body>

</body>
</html>

Saya pikir ada penggunaan yang sangat nyata untuk 2 jenis yang berbeda di sini.

EndangeredMassa
sumber
Dan dalam prototipe saya pikir, apakah anggota null atau hanya tidak terdefinisi.
Kev
tetapi ini hanya bekerja selama tidak ada yang mencoba untuk memecahkannya - jika saya set obj.userid = undefined, itu akan gagal - lihat edit terakhir untuk pertanyaan saya
Christoph
0

Apa yang terjadi adalah sifat dinamis javascript.

Hal-hal mungkin tidak ditentukan sehingga bisa ditambahkan di lain waktu. Ini bisa dibilang mengapa javascript sangat kuat dan dapat dikembangkan.

Rob Stevenson-Leggett
sumber
dan ini relevan dengan pertanyaan saya dalam hal apa?
Christoph
2
Ini relevan karena menjawab pertanyaan Anda. 'null' adalah jenis 'singleton' yang berarti 'tidak memiliki nilai'. 'undefined' memberi tahu Anda bahwa ada sesuatu yang ... mengejutkan, saya tahu ... tidak ditentukan. Mereka sangat berbeda.
rfunduk
0

itu adalah fitur bahasa yang penting jika Anda membungkus program Anda di sekitar paradigma peristiwa javascript.

// a key exists as a placeholder for something
if(obj[name] === null) 
// no key exists int eh hashtable that is in this object
if(obj[name] === undefined)

ini sangat berguna jika Anda berurusan dengan sekumpulan data yang membutuhkan nilai untuk mewakili 'tidak ada' untuk menunjukkan beberapa tindakan yang berbeda dari menggunakan 'tidak ada' untuk menunjukkan tindakan default.

filter_func_pt = {
  date:function(d){ return Math.round(d.getTime()/1000);},
  user: null,
}

function transform(obj){
    var ret = {};
    for( var prop in obj){
       var f = filter_func_pt[prop];
       if(f)
          ret[prop] = f(obj);
       else if(filter_func_pt[prop] === null)
         continue;
       else
         ret[prop] == obj;
    }
  return ret;
}

var a = {
   date: new Date(),
   user: 'sam'
   votes: [23, 41, 55] 
};

var b = transform(a);

/* b = {
 *    date: 1298582417
 *    votes: [23, 41, 55]
 * }
 */

dalam kode di atas kata kunci null dan server tidak ditentukan sangat jelas dan tujuan yang berbeda. pencarian yang tidak ditemukan di objek filter_func_pt yang mengembalikan tidak terdefinisi berarti menambahkan properti ke objek yang dikembalikan sebagaimana adanya, sedangkan nilai null menunjukkan bahwa nilai harus ditahan, dan tidak ditambahkan, dan adanya nilai sebenarnya di dalamnya. case mewakili fungsi yang digunakan untuk mengubah nilai sebelum menambahkannya ke objek ret .

Fire Crow
sumber
Contoh ini dibuat-buat dan agak tidak masuk akal. Null tidak menjelaskan maksud Anda sama sekali - sebaliknya, ia menutupinya. Anda dapat menggunakan string yang lebih eksplisit untuk memperjelas artinya. Seperti, 'menahan' atau 'strip' dan kemudian Anda juga bisa lebih eksplisit tentang jenis fungsi dan benar-benar memeriksa keberadaan suatu fungsi.
Eric Elliott
0

null itu indah

seperti semua Jenis Live Script lainnya.

mengutip: Dalam JavaScript, ada dua nilai yang pada dasarnya mengatakan 'Saya tidak ada' - tidak ditentukan dan nol.

Mengapa Anda ingin mengatakan hal yang salah ?!

"null" adalah "Objek kosong" seperti "0" adalah "Nomor kosong" . 0, bukan apa-apa -tetapi itu ada sebagai Type of a Number. null tentu saja juga kosong tetapi "itu" dan itu adalah hal yang didefinisikan dengan baik dari Tipe Objek .

Adalah umum untuk membicarakan hal ini sebagai "tipe", padahal bukan. Sebenarnya mereka adalah "kategori". Tapi itu sudah berakhir sekarang.

Jadi akan tetap untuk mengatakan bahwa "null" adalah Jenis Objek tanpa Jenis. Dan "null" mengatakan "Saya sangat eksis [!], Tapi saya tidak memiliki konten sejenis".

Sedangkan undefined tidak memiliki Type dan Kind dimana undefined kebetulan juga merupakan definisi Type-nya. Jenis tipe yang tidak terdefinisi menjadi tipologi khasnya. Semacam pertanyaan [apakah "tidak ada" dan bagaimana Anda mendefinisikan "tidak ada"?].

cite: undefined atau null dapat dikembalikan dari fungsi konstruktor, karena keduanya akan diubah menjadi objek kosong

Anda telah berhasil mengatakan hal yang salah sekali lagi. Tentu saja tidak, "undefined" bukanlah sebuah Object, itu adalah Token biasa yang kita manusia pahami; tetapi bertentangan dengan null itu - dan ini memberi tahu Anda bahwa: Type-nya benar, tetapi Jenis yang Anda cari tidak terkandung di dalamnya, atau setidaknya -tidak saat ini. Kunjungi kami nanti saat kami memasukkan \ menetapkan beberapa objek \ ke dalamnya.

mengutip: Satu-satunya perbedaan nyata yang dapat saya pikirkan adalah bahwa yang satu mengevaluasi ke NaN, yang lainnya ke 0 dalam konteks numerik.

Itu membuat inti dari perbedaan inti mereka, seperti yang disebutkan: undefined adalah tanda biasa dan karena itu terdiri dari materi 'genetik' yang sama dengan kerabat jauhnya: string, operasi [+ undefined] akan mengubahnya menjadi NaN, demikian pula null tentu saja akan berubah menjadi jenis 0 \ Number yang benar, dan sebagai lawan dari undefined yang akan berubah menjadi string (! Yang tidak kosong!) Dan itulah mengapa ia menghasilkan NaN sebagai gantinya. Dimana: + undefined >> + "undefined" >> NaN. Karena konteks numerik mengharapkan nilai eksplisit.

Sementara konteks Boolean mengharapkan referensi - tidak menemukan apa pun untuk dikonversi dan menghasilkan 'salah'.

Mari kita hentikan sekarang ...

mengutip: Jadi sekali lagi: apa kegunaan praktis untuk nilai terpisah untuk undefined dan null?

Saya akan mencoba memberi Anda hanya dua contoh empiris dan berharap cukup

oElement.onclick >> null

// Berarti-properti ada; nilai yang diharapkan adalah Type: Object , dan oElement mendukung event "onclick"!

oElement.innerText >> ""

// berarti - properti itu ada; nilai yang diharapkan adalah Type: String , yang berarti oElement mendukung properti "innerText".

pada kedua kasus -jika Anda menerima "tidak ditentukan" itu berarti bahwa properti tidak ada; tidak didukung atau memiliki implementasi (ua vendor) yang salah.

Tetap dingin dan bersenang-senang.

Bill the Lizard
sumber
Jangan merusak postingan Anda, aeneas. Hapus mereka (menggunakan tombol Hapus tepat di atas komentar ini) jika Anda ingin menghapus kontribusi Anda.
Michael Petrotta
tidak ada tombol hapus - tetapi jika Anda melihatnya -harap klik!
0

setelah membaca diskusi yang luar biasa tentang undefined vs null, sedikit pencarian di google membawa saya ke Mozilla Documentations https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null itu disebutkan - sering null diambil di tempat di mana suatu objek dapat diharapkan tetapi tidak ada objek yang relevan.

Tidak mirip dengan pola objek Null https://en.wikipedia.org/wiki/Null_object_pattern

Jadi saya rasa ini masuk akal untuk memiliki tipe data Null.

Dokumentasi juga disebut sebagai tipe null // "object" (bukan "null" karena alasan lama)

Tidak yakin apa alasan warisannya

Vishal Bhandare
sumber