Apakah ada perbedaan antara mendeklarasikan variabel:
var a=0; //1
...cara ini:
a=0; //2
...atau:
window.a=0; //3
dalam lingkup global?
Apakah ada perbedaan antara mendeklarasikan variabel:
var a=0; //1
...cara ini:
a=0; //2
...atau:
window.a=0; //3
dalam lingkup global?
Jawaban:
Ya, ada beberapa perbedaan, meskipun secara praktis mereka biasanya tidak besar.
Ada cara keempat, dan pada ES2015 (ES6) ada dua lagi. Saya telah menambahkan cara keempat di akhir, tetapi memasukkan cara ES2015 setelah # 1 (Anda akan melihat alasannya), jadi kami memiliki:
var a = 0; // 1
let a = 0; // 1.1 (new with ES2015)
const a = 0; // 1.2 (new with ES2015)
a = 0; // 2
window.a = 0; // 3
this.a = 0; // 4
# 1 var a = 0;
Ini menciptakan variabel global yang juga merupakan properti dari objek global , yang kami akses seperti windowpada browser (atau melalui thislingkup global, dalam kode non-ketat). Tidak seperti beberapa properti lain, properti tidak dapat dihapus melalui delete.
Dalam istilah spesifikasi, ini menciptakan pengidentifikasi yang mengikat pada objek Catatan Lingkungan untuk lingkungan global . Itu membuatnya menjadi properti dari objek global karena objek global adalah tempat pengikat ikatan untuk objek lingkungan global Catatan Lingkungan diadakan. Inilah sebabnya mengapa properti tidak dapat dihapus: Ini bukan hanya properti sederhana, ini adalah pengikat pengikat.
Pengikatan (variabel) didefinisikan sebelum baris pertama kode dijalankan (lihat "Ketika varterjadi" di bawah).
Perhatikan bahwa pada IE8 dan sebelumnya, properti dibuat pada windowtidak enumerable (tidak muncul di for..inlaporan). Di IE9, Chrome, Firefox, dan Opera, ini dapat dihitung.
# 1.1 let a = 0;
Ini menciptakan variabel global yang bukan properti dari objek global. Ini adalah hal baru pada ES2015.
Dalam istilah spesifikasi, ini menciptakan pengidentifikasi yang mengikat pada Catatan Lingkungan deklaratif untuk lingkungan global daripada objek Catatan Lingkungan. Lingkungan global adalah unik dalam memiliki split Lingkungan Record, satu untuk semua barang-barang lama yang terjadi di obyek global (yang objek Lingkungan Record) dan satu lagi untuk semua barang baru ( let, const, dan fungsi-fungsi yang dibuat oleh class) yang tidak pergi pada objek global.
Ikatan dibuat sebelum kode langkah-demi-langkah di blok terlampir dijalankan (dalam hal ini, sebelum kode global dijalankan), tetapi tidak dapat diakses dengan cara apa pun sampai eksekusi langkah-demi-langkah mencapai letpernyataan. Setelah eksekusi mencapai letpernyataan, variabel dapat diakses. (Lihat "Kapan letdan constterjadi" di bawah.)
# 1.2 const a = 0;
Menciptakan konstanta global, yang bukan properti dari objek global.
constpersis seperti letkecuali bahwa Anda harus memberikan inisialisasi ( = valuebagian), dan Anda tidak dapat mengubah nilai konstanta setelah itu dibuat. Di bawah selimut, persis seperti lettetapi dengan bendera pada pengenal yang mengikat mengatakan nilainya tidak dapat diubah. Menggunakan constmelakukan tiga hal untuk Anda:
# 2 a = 0;
Ini menciptakan properti pada objek global secara implisit . Karena ini properti biasa, Anda dapat menghapusnya. Saya sarankan tidak melakukan ini, tidak jelas bagi siapa pun yang membaca kode Anda nanti. Jika Anda menggunakan mode ketat ES5, melakukan ini (menugaskan ke variabel tidak ada) adalah kesalahan. Itu salah satu dari beberapa alasan untuk menggunakan mode ketat.
Dan yang menarik, lagi pada IE8 dan sebelumnya, properti yang dibuat tidak dapat dihitung (tidak muncul dalam for..inpernyataan). Itu aneh, terutama diberi # 3 di bawah ini.
# 3 window.a = 0;
Ini menciptakan properti pada objek global secara eksplisit, menggunakan windowglobal yang merujuk pada objek global (pada browser; beberapa lingkungan non-browser memiliki variabel global yang setara, seperti globalpada NodeJS). Karena ini properti biasa, Anda dapat menghapusnya.
Properti ini enumerable, pada IE8 dan sebelumnya, dan pada setiap browser lain yang pernah saya coba.
# 4 this.a = 0;
Persis seperti # 3, kecuali kita mereferensikan objek global melalui thisalih-alih global window. Ini tidak akan bekerja dalam mode ketat, karena dalam mode global kode ketat, thistidak memiliki referensi ke objek global (ia memiliki nilai undefinedsebagai gantinya).
Apa yang saya maksud dengan "menghapus" atau "menghapus" a? Tepatnya: Menghapus properti (seluruhnya) melalui deletekata kunci:
window.a = 0;
display("'a' in window? " + ('a' in window)); // displays "true"
delete window.a;
display("'a' in window? " + ('a' in window)); // displays "false"
deletesepenuhnya menghapus properti dari objek. Anda tidak dapat melakukannya dengan properti yang ditambahkan windowsecara tidak langsung melalui var, deletediabaikan secara diam-diam atau melempar pengecualian (tergantung pada implementasi JavaScript dan apakah Anda dalam mode ketat).
Peringatan : IE8 lagi (dan mungkin sebelumnya, dan IE9-IE11 dalam mode "kompatibilitas" yang rusak): Itu tidak akan membiarkan Anda menghapus properti windowobjek, bahkan ketika Anda seharusnya diizinkan. Lebih buruk, itu melempar pengecualian ketika Anda mencoba ( coba percobaan ini di IE8 dan di browser lain). Jadi ketika menghapus dari windowobjek, Anda harus bersikap defensif:
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
Itu mencoba untuk menghapus properti, dan jika pengecualian dilemparkan itu melakukan hal terbaik berikutnya dan menyetel properti undefined.
Ini hanya berlaku untuk windowobjek, dan hanya (sejauh yang saya tahu) ke IE8 dan sebelumnya (atau IE9-IE11 dalam mode "kompatibilitas" yang rusak). Browser lain baik-baik saja dengan menghapus windowproperti, tunduk pada aturan di atas.
varterjadiVariabel didefinisikan melalui varpernyataan yang dibuat sebelum setiap langkah-demi-langkah kode dalam konteks eksekusi dijalankan, dan properti ada juga sebelum itu varpernyataan.
Ini bisa membingungkan, jadi mari kita lihat:
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "undefined"
display("bar in window? " + ('bar' in window)); // displays "false"
display("window.bar = " + window.bar); // displays "undefined"
var foo = "f";
bar = "b";
display("foo in window? " + ('foo' in window)); // displays "true"
display("window.foo = " + window.foo); // displays "f"
display("bar in window? " + ('bar' in window)); // displays "true"
display("window.bar = " + window.bar); // displays "b"
Contoh langsung:
Seperti yang Anda lihat, simbol foodidefinisikan sebelum baris pertama, tetapi simbol baritu tidak. Di mana var foo = "f";pernyataan itu, sebenarnya ada dua hal: mendefinisikan simbol, yang terjadi sebelum baris pertama kode dijalankan; dan melakukan penugasan untuk simbol itu, yang terjadi di mana garis berada dalam aliran langkah demi langkah. Ini dikenal sebagai " varmengangkat" karena var foobagian tersebut dipindahkan ("diangkat") ke bagian atas ruang lingkup, tetapi foo = "f"bagian tersebut dibiarkan di lokasi aslinya. (Lihat Miskin disalahpahamivar di blog kecil anemia saya.)
letdan constterjadiletdan constberbeda vardalam beberapa hal. Cara yang relevan dengan pertanyaan adalah bahwa meskipun ikatan yang mereka tetapkan dibuat sebelum kode langkah-demi-langkah berjalan, itu tidak dapat diakses sampai pernyataan letatau consttercapai.
Jadi sementara ini berjalan:
display(a); // undefined
var a = 0;
display(a); // 0
Ini menimbulkan kesalahan:
display(a); // ReferenceError: a is not defined
let a = 0;
display(a);
Dua cara lain yang letdan constberbeda var, yang tidak benar-benar relevan dengan pertanyaan, adalah:
varselalu berlaku untuk seluruh konteks eksekusi (seluruh kode global, atau seluruh kode fungsi pada fungsi yang muncul), tetapi letdan consthanya berlaku di dalam blok tempat mereka muncul. Artinya, varmemiliki lingkup fungsi (atau global), tetapi letdan constmemiliki lingkup blok.
Mengulangi var adalam konteks yang sama tidak berbahaya, tetapi jika Anda memiliki let a(atau const a), memiliki lain let aatau const aatau var amerupakan kesalahan sintaks.
Berikut ini contoh yang menunjukkan hal itu letdan constsegera berlaku di blok mereka sebelum kode apa pun di dalam blok itu berjalan, tetapi tidak dapat diakses hingga pernyataan letatau const:
var a = 0;
console.log(a);
if (true)
{
console.log(a); // ReferenceError: a is not defined
let a = 1;
console.log(a);
}
Perhatikan bahwa yang kedua console.loggagal, alih-alih mengakses adari luar blok.
window)The windowobjek akan sangat, sangat penuh dengan sifat. Kapan pun memungkinkan, sangat disarankan untuk tidak menambah kekacauan. Sebagai gantinya, bungkus simbol Anda dalam paket kecil dan ekspor paling banyak satu simbol ke windowobjek. (Saya sering tidak mengekspor simbol apa pun ke windowobjek.) Anda dapat menggunakan fungsi untuk memuat semua kode Anda agar mengandung simbol Anda, dan fungsi itu bisa anonim jika Anda suka:
(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
Dalam contoh itu, kita mendefinisikan suatu fungsi dan langsung menjalankannya ( ()akhir).
Fungsi yang digunakan dengan cara ini sering disebut fungsi pelingkupan . Fungsi didefinisikan dalam fungsi scoping variabel akses dapat didefinisikan dalam fungsi scoping karena mereka penutupan atas data itu (lihat: Penutup tidak rumit di blog sedikit anemia saya).
window['a']=0untuk membuatnya jelas saya menggunakan jendela sebagai peta? Apakah windowspesial sehingga beberapa browser tidak mengizinkan ini dan memaksa saya untuk menggunakan window.a?
window.a = 0;hanya berfungsi di lingkungan peramban, dan hanya dengan konvensi. Mengikat objek global ke variabel yang bernama windowtidak ada dalam ES Spec dan karenanya tidak akan berfungsi, misalnya, V8 atau Node.js, sementara this.a = 0;(ketika dipanggil dalam konteks eksekusi global) akan bekerja di lingkungan apa pun karena spec tidak menentukan bahwa harus ada sebuah obyek global. Jika membungkus kode Anda dalam IIFE seperti di bagian Off-topic , Anda dapat lulus thissebagai parameter bernama windowatau globaluntuk mendapatkan referensi langsung ke objek global.
var a = 0;otomatis menjadi properti dari objek global. Jika saya mendeklarasikan var b = 0;dalam deklarasi fungsi, apakah itu juga akan menjadi properti dari beberapa objek yang mendasarinya?
Tetap sederhana:
a = 0
Kode di atas memberikan variabel lingkup global
var a = 0;
Kode ini akan memberikan variabel untuk digunakan dalam lingkup saat ini, dan di bawahnya
window.a = 0;
Ini umumnya sama dengan variabel global.
a di bawah ini lingkup saat ini. Kamu bisa. Selain itu, penggunaan "variabel global" Anda sedikit salah - dua tempat yang Anda katakan "variabel global" tidak lebih global daripada tempat yang tidak Anda katakan.
<title>Index.html</title>
<script>
var varDeclaration = true;
noVarDeclaration = true;
window.hungOnWindow = true;
document.hungOnDocument = true;
</script>
<script src="external.js"></script>
/* external.js */
console.info(varDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(noVarDeclaration == true); // could be .log, alert etc
// returns false in IE8
console.info(window.hungOnWindow == true); // could be .log, alert etc
// returns true in IE8
console.info(document.hungOnDocument == true); // could be .log, alert etc
// returns ??? in IE8 (untested!) *I personally find this more clugy than hanging off window obj
Apakah ada objek global yang semua vars digantung secara default? mis: 'deklarasi global.noVar'
window.*deklarasi. Deklarasi ini terlihat paling aman terhadap copy-paste kode Anda, dan hapus juga.
Bass pada jawaban yang sangat baik dari TJ Crowder : ( Di luar topik: Hindari berantakanwindow )
Ini adalah contoh dari idenya:
Html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="init.js"></script>
<script type="text/javascript">
MYLIBRARY.init(["firstValue", 2, "thirdValue"]);
</script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello !</h1>
</body>
</html>
init.js (Berdasarkan jawaban ini )
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {}; // private
return {
init : function(Args) {
_args = Args;
// some other initialising
},
helloWorld : function(i) {
return _args[i];
}
};
}());
script.js
// Here you can use the values defined in the html as if it were a global variable
var a = "Hello World " + MYLIBRARY.helloWorld(2);
alert(a);
Inilah plnkrnya . Semoga ini bisa membantu!
Dalam lingkup global tidak ada perbedaan semantik.
Tetapi Anda harus benar-benar menghindari a=0karena menetapkan nilai ke variabel yang tidak dideklarasikan.
Juga gunakan penutupan untuk menghindari mengedit ruang lingkup global sama sekali
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
Selalu gunakan penutupan dan selalu angkat ke ruang lingkup global ketika itu benar-benar diperlukan. Anda harus menggunakan penanganan acara yang tidak sinkron untuk sebagian besar komunikasi Anda.
Seperti @AvianMoncellor menyebutkan ada bug IE dengan var a = foohanya mendeklarasikan global untuk cakupan file. Ini adalah masalah dengan interpreter rusak IE yang terkenal. Bug ini memang terdengar familier sehingga mungkin benar.
Jadi berpegang teguh pada window.globalName = someLocalpointer
deletea var).
var. Mereka hanya mekanisme yang sama sekali berbeda yang memiliki hasil praktis yang sama. :-)
varmelompat ke berhenti lingkup.