Seberapa berbahayanya di JavaScript, sungguh, menganggap undefined tidak ditimpa?

87

Setiap kali ada yang menyebutkan pengujian terhadap undefined, itu menunjukkan bahwa undefineditu bukan kata kunci sehingga dapat diatur ke"hello" , jadi Anda harus menggunakan typeof x == "undefined" sebagai gantinya. Ini tampak konyol bagi saya. Tidak ada yang akan pernah melakukan itu, dan jika mereka melakukannya, itu akan menjadi alasan yang cukup untuk tidak pernah menggunakan kode apa pun yang mereka tulis ... bukan?

Saya menemukan satu contoh dari seseorang yang secara tidak sengaja mengatur undefinedke null, dan ini diberikan sebagai alasan untuk menghindari asumsi yang undefinedtidak ditimpa. Tetapi jika mereka melakukan itu, bug tidak akan terdeteksi, dan saya gagal untuk melihat bagaimana itu lebih baik.

Di C ++ semua orang sangat sadar bahwa itu legal untuk mengatakannya #define true false, tetapi tidak ada yang menyarankan Anda menghindari truedan menggunakan 0 == 0sebagai gantinya. Anda hanya berasumsi bahwa tidak ada orang yang cukup brengsek untuk melakukan itu, dan jika mereka melakukannya, jangan pernah mempercayai kode mereka lagi.

Pernahkah ini benar-benar menggigit seseorang di mana orang lain ditugaskan undefined(dengan sengaja) dan itu memecahkan kode Anda, atau apakah ini lebih merupakan ancaman hipotetis? Saya bersedia mengambil kesempatan saya untuk membuat kode saya sedikit lebih mudah dibaca. Apakah ini ide yang buruk?

Untuk mengulangi, saya tidak menanyakan cara melindungi dari penetapan ulang yang tidak ditentukan. Saya telah melihat trik itu ditulis 100 kali. Saya bertanya betapa berbahayanya tidak menggunakan trik-trik itu.

Kosmologikon
sumber
7
Saya akan senang, tetapi saya merasa salah satu dari tiga jawaban yang diberikan tidak menjawab pertanyaan dengan baik. Saya mencoba menjelaskan bahwa saya tidak meminta pengulangan jawaban yang saya tautkan, tetapi itulah yang saya dapatkan. Jika dianggap tidak sopan untuk tidak menerima jawaban meskipun bukan itu yang saya tanyakan, beri tahu saya dan saya akan melanjutkan dan menerimanya!
Cosmologicon
1
Saya pikir semua fakta dijelaskan di sini. Jadi, yang Anda katakan adalah Anda menginginkan jawaban atau pendapat subjektif, yang hanya mengarah pada perselisihan. Itulah alasan frasa "praktik terbaik" tidak diizinkan dalam judul pertanyaan. Anda adalah satu-satunya orang yang bisa mengetahui betapa berbahayanya skenario Anda. Dan jika Anda menulis pustaka populer di mana Anda tidak mengontrol semua 'variabel', fungsi (undefined) {} ​​pembungkus tampaknya menjadi jawaban yang sangat baik. Mengapa tidak menggunakannya dan menerima jawaban itu?
shannon
4
Jika ada yang khawatir tentang definisi ulang seseorang undefined, Anda harus lebih khawatir tentang definisi ulang seseorang XMLHttpRequest, atau alert. Semua fungsi yang kami gunakan windowdapat didefinisikan ulang. Dan jika Anda hanya khawatir tentang rekan kerja yang melakukannya secara tidak sengaja, mengapa mempercayai mereka untuk tidak melakukannya window.addEventListener = "coolbeans"? Jawabannya adalah jangan khawatir tentang semua itu. Jika seseorang dengan jahat memasukkan JS ke halaman Anda, Anda tetap disemprot. Bekerja untuk mencegah hal itu terjadi sejak awal.
Chris Middleton

Jawaban:

57

Tidak, saya tidak pernah. Ini sebagian besar karena saya mengembangkan di browser modern, yang sebagian besar sesuai dengan ECMAScript 5. Standar ES5 menentukan yang undefinedsekarang hanya bisa dibaca. Jika Anda menggunakan mode ketat (Anda harus), kesalahan akan muncul jika Anda secara tidak sengaja mencoba untuk memodifikasinya.

undefined = 5;
alert(undefined); // still undefined
'use strict';
undefined = 5; // throws TypeError

Yang tidak boleh Anda lakukan adalah membuat cakupan Anda sendiri, bisa berubah undefined:

(function (undefined) {
    // don't do this, because now `undefined` can be changed
    undefined = 5;
})();

Konstan baik-baik saja. Masih tidak perlu, tapi bagus.

(function () {
    const undefined = void 0;
})();
Ry-
sumber
Pernyataan pertama Anda hanya memastikan bahwa Anda tidak secara tidak sengaja menimpa undefined saat mengembangkan, pernyataan tersebut masih menimbulkan ancaman yang sama saat dijalankan dengan kode lain di komputer klien.
bennedich
1
@ Bennedich: Saya tahu, saya mengatakan saya tidak pernah mengalami masalah itu, tapi inilah yang harus Anda lakukan .
Ry-
1
@bennedich Apakah Anda tidak memiliki kesempatan yang sama untuk secara tidak sengaja menimpa variabel lain?
Ates Goral
40

Tidak ada kode yang tepat yang akan melakukan hal seperti itu. Tetapi Anda tidak akan pernah tahu apa yang dilakukan oleh beberapa pengembang cerdas wannabe atau plugin / perpustakaan / skrip yang Anda gunakan. Di sisi lain, ini sangat tidak mungkin dan peramban modern tidak mengizinkan penimpaan undefinedsama sekali, jadi jika Anda menggunakan peramban semacam itu untuk pengembangan, Anda akan segera melihat jika ada kode yang mencoba menimpanya.


Dan meskipun Anda tidak memintanya - banyak orang mungkin akan menemukan pertanyaan ini ketika mencari masalah "bagaimana melindungi dari definisi ulang undefined" yang lebih umum , jadi saya akan menjawabnya:

Ada cara yang sangat bagus untuk mendapatkan yang benar-benar tidak terdefinisi undefined tidak peduli berapa umur browsernya:

(function(undefined) {
    // your code where undefined is undefined
})();

Ini berfungsi karena argumen yang tidak ditentukan selalu undefined. Anda juga dapat melakukannya dengan fungsi yang menerima beberapa argumen nyata, misalnya seperti ini saat Anda menggunakan jQuery. Biasanya merupakan ide bagus untuk memastikan lingkungan yang sehat dengan cara ini:

(function($, window, undefined) {
    // your code where undefined is undefined
})(jQuery, this);

Kemudian Anda dapat yakin bahwa di dalam fungsi anonim itu hal-hal berikut ini benar:

  • $ === jQuery
  • window === [the global object]
  • undefined === [undefined].

Namun, perhatikan bahwa kadang-kadang typeof x === 'undefined'sebenarnya diperlukan: Jika variabel xtidak pernah set ke nilai (bertentangan dengan menjadi set ke undefined), membaca xdengan cara yang berbeda seperti if(x === undefined)akan melemparkan kesalahan. Ini tidak berlaku untuk properti objek, jadi jika Anda tahu itu yselalu merupakan objek, if(y.x === undefined)sangat aman.

ThiefMaster
sumber
2
Pernyataan Anda tentang xtidak disetel ke nilai tidak sepenuhnya benar (lihat jsfiddle.net/MgADz ); itu bukan jika sebenarnya benar-benar tidak ditentukan (lihat jsfiddle.net/MgADz/1 ).
Ry-
7
Sekali lagi, jika seseorang secara tidak sengaja mengatakan undefined = someVariableitu bug dan Anda ingin semuanya rusak. Setidaknya saya lakukan.
Cosmologicon
2
Saya telah bekerja dengan basis kode yang memiliki skrip lawas yang diperkecil yang menimpa tidak terdefinisi, kami tidak punya waktu atau anggaran untuk menulis ulang skrip, ini adalah contoh di mana tipe x == "tidak ditentukan" diperlukan, itu tidak terlalu aneh dan mungkin kebiasaan yang baik.
Damen TheSifter
2
Saya tertarik dengan mengapa semua contoh menggunakan "tidak ditentukan" sebagai argumen tambahan dalam fungsi? Tetapi ada situasi jika seseorang melewatkan satu parameter tambahan (ditentukan) oleh kesalahan dan semua logika akan gagal. Mengapa tidak menggunakan sesuatu seperti function () {var _undef; if (someVal == _undef) {do something}};
Oleksandr_DJ
4
@Oleksa Membuat nilai yang Anda tahu adalah undefineddan menetapkan bahwa untuk undefineddalam lingkup. Jangan biarkan undefinedterbuka untuk ditimpa jika Anda menyampaikan "terlalu banyak" argumen. Itu mengundang kesalahan, dan secara inheren merupakan pola non-defensif, terutama ketika, seperti yang ditunjukkan Lucero , ada alternatif yang sangat mudah untuk mendapatkan undefinednilai yang solid dalam lingkup.
ruffin
19

Ada solusi sederhana untuk itu: bandingkan dengan void 0yang selalu tidak ditentukan.

Perhatikan bahwa Anda harus menghindari ==karena dapat memaksa nilai. Gunakan ===(dan !==) sebagai gantinya.

Meskipun demikian, variabel tak terdefinisi dapat disetel dengan kesalahan jika seseorang menulis =alih-alih ==saat membandingkan sesuatu undefined.

Lucero
sumber
IMO, ini jawaban terbaik.
abhisekp
1
Pertimbangkan bahwa foo === void 0pembacaan mungkin tidak semulus foo === undefineddan yang tidak undefineddapat diubah didukung sepenuhnya oleh browser modern (IE 9+) seperti yang Anda lihat di tabel kompatibilitas ini .
Daniel AR Werner
3

Hanya Anda yang tahu kode apa yang Anda gunakan, dan oleh karena itu betapa berbahayanya itu. Pertanyaan ini tidak dapat dijawab dengan cara Anda mengklarifikasi bahwa Anda ingin dijawab.

1) Buat kebijakan tim, larang definisi ulang yang tidak ditentukan, simpan untuk penggunaan yang lebih populer. Pindai kode Anda yang ada untuk tugas kiri yang tidak ditentukan.

2) Jika Anda tidak mengontrol semua skenario, jika kode Anda digunakan di luar situasi yang Anda atau kebijakan Anda kendalikan, maka jelas jawaban Anda berbeda. Pindai kode yang menggunakan skrip Anda. Heck, pindai web untuk statistik tugas kiri yang tidak ditentukan jika Anda mau, tetapi saya ragu itu telah dilakukan untuk Anda, karena lebih mudah untuk hanya mengejar jawaban # 1 atau # 3 di sini.

3) Dan jika jawaban itu tidak cukup baik, mungkin karena, sekali lagi, Anda memerlukan jawaban yang berbeda. Mungkin Anda sedang menulis perpustakaan populer yang akan digunakan di dalam firewall perusahaan, dan Anda tidak memiliki akses ke kode panggilan. Kemudian gunakan salah satu jawaban bagus lainnya di sini. Perhatikan pustaka jQuery yang populer mempraktikkan enkapsulasi suara, dan mulai:

(function( window, undefined ) {

Hanya Anda yang dapat menjawab pertanyaan Anda dengan cara yang Anda cari. Apa lagi yang bisa kukatakan?

edit: ps jika Anda benar-benar menginginkan pendapat saya, saya akan memberi tahu Anda itu tidak berbahaya sama sekali. Apa pun yang sangat mungkin menyebabkan cacat (seperti menetapkan ke tidak ditentukan, yang jelas merupakan perilaku berisiko yang terdokumentasi dengan baik) dengan sendirinya merupakan cacat. Cacat itulah risikonya. Tapi itu hanya dalam skenario saya, di mana saya mampu mempertahankan perspektif itu. Seperti yang saya sarankan Anda lakukan, saya menjawab pertanyaan untuk kasus penggunaan saya.

shannon
sumber
3

Aman untuk diuji dengan yang tidak ditentukan. Seperti yang sudah Anda sebutkan. Jika Anda mendapatkan beberapa kode yang menimpanya (yang sangat dapat ditingkatkan), jangan gunakan lagi.

Mungkin jika Anda membuat perpustakaan untuk penggunaan umum, Anda dapat menggunakan beberapa teknik untuk menghindari pengguna mengubahnya. Tetapi bahkan dalam kasus ini, itu masalah mereka, bukan perpustakaan Anda.

Bart Calixto
sumber
2

Anda dapat menggunakan undefinedkode Anda saat membuat kode untuk browser yang mendukung ECMAScript 5.1 karena kode tersebut tidak dapat diubah sesuai dengan spesifikasi bahasa .

Lihat juga tabel kompatibilitas ini atau ECMAScript 5 caniuse ini untuk melihat bahwa semua browser modern (IE 9+) telah menerapkan immutable .undefined

Daniel AR Werner
sumber
1

Itu tidak berbahaya sama sekali. Ini hanya dapat ditimpa saat dijalankan pada mesin ES3 dan kemungkinan besar tidak akan digunakan lagi.

kirk.burleson
sumber
0

Pertama-tama, jika kode Anda rusak, itu mungkin bukan karena beberapa pengembang lain di luar sana "mencoba menjadi brengsek" seperti yang Anda katakan.

Memang benar itu undefinedbukan kata kunci. Tapi itu adalah primitif tingkat global. Itu dimaksudkan untuk digunakan seperti ini (lihat "tidak ditentukan" di developer.mozilla.org ):

var x;
if (x === undefined) {
    // these statements execute
}
else {
    // these statements do not execute
}

Alternatif umum untuk itu (juga dari MDN ) dan menurut saya cara yang lebih baik adalah:

// x has not been declared before
if (typeof x === 'undefined') { // evaluates to true without errors
    // these statements execute
}

if(x === undefined){ // throws a ReferenceError

}

Yang memiliki beberapa keuntungan, yang jelas (dari komentar) adalah tidak memicu pengecualian ketika x tidak dideklarasikan. Juga perlu dicatat bahwa MDN juga menunjukkan bahwa penting untuk digunakan ===kembali ==dalam kasus pertama karena:

var x=null;
if (x === undefined) {
    // this is probably what you meant to do
    // these lines will not execute in this case
}
else if (x == undefined) {
    // these statements will execute even though x *is* defined (as null)
}
else {
    // these statements do not execute
}

Ini adalah alasan lain yang sering diabaikan mengapa mungkin lebih baik menggunakan alternatif kedua dalam semua kasus.

Kesimpulan: Tidak salah mengkodekannya dengan cara pertama, dan tentunya tidak berbahaya. Argumen yang Anda lihat yang Anda gunakan sebagai contoh untuk melawannya (yang dapat ditimpa) bukanlah argumen terkuat untuk mengkodekan alternatif dengan typeof. Tetapi penggunaan typeoflebih kuat karena satu alasan khusus: itu tidak memunculkan pengecualian saat var Anda tidak dideklarasikan. Dapat juga dikatakan bahwa menggunakan ==bukan ===merupakan kesalahan umum dalam hal ini tidak melakukan apa yang Anda harapkan. Jadi mengapa tidak digunakan typeof?

Gurita
sumber
1
"Yang memiliki beberapa keuntungan, yang jelas adalah tidak memicu pengecualian saat x tidak dideklarasikan." Biarkan aku meluruskan ini. Anda pikir itu sebuah keuntungan untuk diam-diam mengabaikan pengecualian yang terjadi ketika Anda menggunakan variabel dideklarasikan? Tampaknya sangat rawan kesalahan. Bisakah Anda menjelaskan mengapa menurut Anda hal itu tidak merugikan?
Cosmologicon