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 window
pada browser (atau melalui this
lingkup 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 var
terjadi" di bawah).
Perhatikan bahwa pada IE8 dan sebelumnya, properti dibuat pada window
tidak enumerable (tidak muncul di for..in
laporan). 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 let
pernyataan. Setelah eksekusi mencapai let
pernyataan, variabel dapat diakses. (Lihat "Kapan let
dan const
terjadi" di bawah.)
# 1.2 const a = 0;
Menciptakan konstanta global, yang bukan properti dari objek global.
const
persis seperti let
kecuali bahwa Anda harus memberikan inisialisasi ( = value
bagian), dan Anda tidak dapat mengubah nilai konstanta setelah itu dibuat. Di bawah selimut, persis seperti let
tetapi dengan bendera pada pengenal yang mengikat mengatakan nilainya tidak dapat diubah. Menggunakan const
melakukan 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..in
pernyataan). Itu aneh, terutama diberi # 3 di bawah ini.
# 3 window.a = 0;
Ini menciptakan properti pada objek global secara eksplisit, menggunakan window
global yang merujuk pada objek global (pada browser; beberapa lingkungan non-browser memiliki variabel global yang setara, seperti global
pada 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 this
alih-alih global window
. Ini tidak akan bekerja dalam mode ketat, karena dalam mode global kode ketat, this
tidak memiliki referensi ke objek global (ia memiliki nilai undefined
sebagai gantinya).
Apa yang saya maksud dengan "menghapus" atau "menghapus" a
? Tepatnya: Menghapus properti (seluruhnya) melalui delete
kata 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"
delete
sepenuhnya menghapus properti dari objek. Anda tidak dapat melakukannya dengan properti yang ditambahkan window
secara tidak langsung melalui var
, delete
diabaikan 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 window
objek, 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 window
objek, 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 window
objek, 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 window
properti, tunduk pada aturan di atas.
var
terjadiVariabel didefinisikan melalui var
pernyataan yang dibuat sebelum setiap langkah-demi-langkah kode dalam konteks eksekusi dijalankan, dan properti ada juga sebelum itu var
pernyataan.
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 foo
didefinisikan sebelum baris pertama, tetapi simbol bar
itu 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 " var
mengangkat" karena var foo
bagian 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.)
let
dan const
terjadilet
dan const
berbeda var
dalam 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 let
atau const
tercapai.
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 let
dan const
berbeda var
, yang tidak benar-benar relevan dengan pertanyaan, adalah:
var
selalu berlaku untuk seluruh konteks eksekusi (seluruh kode global, atau seluruh kode fungsi pada fungsi yang muncul), tetapi let
dan const
hanya berlaku di dalam blok tempat mereka muncul. Artinya, var
memiliki lingkup fungsi (atau global), tetapi let
dan const
memiliki lingkup blok.
Mengulangi var a
dalam konteks yang sama tidak berbahaya, tetapi jika Anda memiliki let a
(atau const a
), memiliki lain let a
atau const a
atau var a
merupakan kesalahan sintaks.
Berikut ini contoh yang menunjukkan hal itu let
dan const
segera berlaku di blok mereka sebelum kode apa pun di dalam blok itu berjalan, tetapi tidak dapat diakses hingga pernyataan let
atau 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.log
gagal, alih-alih mengakses a
dari luar blok.
window
)The window
objek 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 window
objek. (Saya sering tidak mengekspor simbol apa pun ke window
objek.) 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']=0
untuk membuatnya jelas saya menggunakan jendela sebagai peta? Apakah window
spesial 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 window
tidak 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 this
sebagai parameter bernama window
atau global
untuk 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=0
karena 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 = foo
hanya 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
delete
a var
).
var
. Mereka hanya mekanisme yang sama sekali berbeda yang memiliki hasil praktis yang sama. :-)
var
melompat ke berhenti lingkup.