Değişken bildirme arasında fark var mı:
var a=0; //1
...bu yoldan:
a=0; //2
...veya:
window.a=0; //3
küresel kapsamda mı?
Değişken bildirme arasında fark var mı:
var a=0; //1
...bu yoldan:
a=0; //2
...veya:
window.a=0; //3
küresel kapsamda mı?
Yanıtlar:
Evet, pratikte genellikle büyük olanlar olmasa da, birkaç fark vardır.
Dördüncü bir yol var ve ES2015 (ES6) itibariyle iki tane daha var. Sonunda dördüncü yolu ekledim, ancak ES2015 yollarını # 1'den sonra ekledim (nedenini göreceksiniz), bu yüzden:
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;
Bu , tarayıcılarda olduğu gibi (veya genel bir kapsam aracılığıyla , katı olmayan kodda) eriştiğimiz global nesnenin bir özelliği olan global bir değişken oluşturur . Diğer bazı özelliklerin aksine, özellik üzerinden kaldırılamaz .window
this
delete
Şartname açısından, bir oluşturur bağlayıcı tanımlayıcı üzerinde nesne Çevre Kayıt için küresel ortamda . Bu, onu global nesnenin bir özelliği yapar, çünkü global nesne, global ortamın nesnesi Ortam Kaydı için tanımlayıcı bağlarının tutulduğu yerdir. Bu nedenle özellik silinebilir değildir: Sadece basit bir özellik değil, tanımlayıcı bir bağlayıcıdır.
Bağlama (değişken) kodun ilk satırı çalışmadan önce tanımlanır (aşağıdaki "Ne zaman var
olur" bölümüne bakın).
Not üzerinde oluşturulan mülkiyet IE8 üzerinde ve daha önce o window
değil enumerable (içinde görünmüyor for..in
ifadeleri). IE9, Chrome, Firefox ve Opera'da numaralandırılabilir.
# 1.1 let a = 0;
Bu , global nesnenin bir özelliği olmayan bir global değişken oluşturur . Bu ES2015'ten itibaren yeni bir şey.
Spesifikasyon terimleriyle, global kayıt için Ortam Kaydı nesnesi yerine bildirimsel Ortam Kaydı üzerinde bir tanımlayıcı bağlayıcı oluşturur . Küresel çevre bir bölünme Çevre Kayıt, küresel nesne (gider eski eşyaları hepsi için tek sahip tektir nesne yeni şeyler herkes için Çevre Record) ve diğeri ( , ve yarattığı fonksiyonlar ) yok küresel nesneye geçin.let
const
class
Olduğu bağlayıcı oluşturulan onu kapsayan blokta herhangi adım adım kodu (herhangi bir genel kod çalışmadan önce, bu durumda) çalıştırılmadan önce, ama değil erişilebilir adım-adım yürütme ulaşıncaya kadar herhangi bir şekilde let
açıklama. Yürütme let
ifadeye ulaştığında, değişken erişilebilir. (Aşağıdaki "Ne zaman let
ve const
gerçekleşir" bölümüne bakın.)
# 1.2 const a = 0;
Genel nesnenin bir özelliği olmayan bir genel sabit oluşturur.
const
Tam gibidir let
Eğer bir başlatıcı (sağlamalıdır dışında = value
kısım) ve oluşturulduktan sonra size sabitinin değerini değiştiremez. Kapakların altında, tam olarak benzer let
ancak tanımlayıcı bağlaması üzerinde bir değerin değiştirilemeyeceğini söyleyen bir bayrak bulunur. Kullanmak const
sizin için üç şey yapar:
2. a = 0;
Bu, dolaylı olarak genel nesne üzerinde bir özellik oluşturur . Normal bir özellik olduğu için silebilirsiniz. Ben tavsiye ederim değil sonradan kodunuzu okuyan herkes için belirsiz olabilir, bunu yaparken. ES5'in katı modunu kullanırsanız, bunu yapmak (var olmayan bir değişkene atama) bir hatadır. Katı modu kullanmak için birkaç nedenden biri.
Ve ilginç bir şekilde, yine IE8 ve öncesinde, numaralandırılamayan özellik oluşturuldu ( for..in
ifadelerde görünmüyor ). Bu garip, özellikle aşağıda # 3 verildi.
3. window.a = 0;
Bu window
, genel nesneyi (tarayıcılarda; tarayıcı olmayan bazı ortamların global
NodeJS gibi eşdeğer bir global değişkeni vardır) kullanan genel nesneyi kullanarak açıkça genel nesne üzerinde bir özellik oluşturur . Normal bir özellik olduğu için silebilirsiniz.
Bu özellik ise IE8 üzerinde, enumerable ve önceki sürümleri ve diğer her tarayıcıda denedim.
4. this.a = 0;
Tam olarak # 3 gibi, ancak global nesneyi global this
yerine referans olarak kullanıyoruz window
. Bu katı modda çalışmaz, çünkü katı modda global kod, this
global nesneye bir referansa sahip değildir (bunun undefined
yerine değeri vardır ).
"Silme" veya "kaldırma" ile ne demek istiyorum a
? Tam olarak: delete
Anahtar kelimeyle özelliği (tamamen) kaldırma :
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
bir özelliği bir nesneden tamamen kaldırır. Sen özellikler eklenmiş ile bunu yapamam window
aracılığıyla dolaylı olarak var
, delete
ya sessizce göz ardı ya da (JavaScript uygulanması ve katı modda ister bağlı olarak) bir istisna atar edilir.
Uyarı : IE8 tekrar (ve muhtemelen daha önce ve kırık "uyumluluk" modunda IE9-IE11): İzin window
vermeniz gerektiğinde bile nesnenin özelliklerini silmenize izin vermez . Daha da kötüsü, denediğinizde bir istisna atar ( bu denemeyi IE8 ve diğer tarayıcılarda deneyin ). Bu yüzden window
nesneden silerken, savunmacı olmalısınız:
try {
delete window.prop;
}
catch (e) {
window.prop = undefined;
}
Bu özelliği silmeye çalışır ve bir istisna atılırsa bir sonraki en iyi şeyi yapar ve özelliği olarak ayarlar undefined
.
Bu sadecewindow
nesne için geçerlidir ve sadece (bildiğim kadarıyla) IE8 ve öncesi (veya kırık "uyumluluk" modunda IE9-IE11) için geçerlidir. Diğer tarayıcılar, window
yukarıdaki kurallara tabi olarak özellikleri silme konusunda iyidir .
var
olurİfade aracılığıyla tanımlanan değişkenler , yürütme bağlamındaki herhangi bir adım adım kod çalıştırılmadan var
önce oluşturulur ve bu nedenle özellik , ifadeden çok önce bulunur .var
Bu kafa karıştırıcı olabilir, bu yüzden bir göz atalım:
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"
Canlı örnek:
Gördüğünüz gibi, sembol foo
ilk satırdan önce tanımlanır, ancak sembol bar
değildir. İfadenin var foo = "f";
olduğu yerde, gerçekten iki şey vardır: ilk kod satırı çalıştırılmadan önce gerçekleşen sembolü tanımlamak; ve çizginin adım adım akışta olduğu yerde gerçekleşen bu sembole bir atama yapmak. Bu, " var
kaldırma" olarak bilinir, çünkü var foo
parça, kapsamın en üstüne taşınır ("kaldırılır"), ancak foo = "f"
parça orijinal konumunda bırakılır. (Bkz. Kötüvar
anemik küçük blogumda yanlış anlaşılmış .)
let
ve const
olurlet
ve const
farklı var
şekillerde bir çift. Sorusuna alakalı yolu bağlayıcı herhangi adım adım kod çalışmadan önce oluşturulan tanımlamak rağmen, o değil ki erişilebilir kadar let
ya const
deyim ulaşılır.
Yani bu çalışırken:
display(a); // undefined
var a = 0;
display(a); // 0
Bu bir hata verir:
display(a); // ReferenceError: a is not defined
let a = 0;
display(a);
Soruyla gerçekten ilgili olmayan let
ve const
farklı olan diğer iki yol var
şunlardır:
var
Her zaman (küresel kod boyunca veya gösterilip işlevinde fonksiyon kodu boyunca) tüm yürütme içeriği için geçerlidir, ancak let
ve const
sadece içinde başvurmaları bloğunun göründükleri. Olduğunu, var
fonksiyonunu (veya global) kapsamı vardır, ama let
ve const
blok kapsamına sahip.
Tekrarlayan var a
aynı bağlamda zararsız olmakla birlikte, varsa let a
(veya const a
), başka sahip let a
veya bir const a
ya da var a
bir yazım hatasıdır.
İşte bunu gösteren let
ve const
bu blok içindeki herhangi bir kod çalışmadan önce hemen bloklarında yürürlüğe girecek, ancak let
veya const
ifadesine kadar erişilemeyen bir örnek :
var a = 0;
console.log(a);
if (true)
{
console.log(a); // ReferenceError: a is not defined
let a = 1;
console.log(a);
}
Bloğun dışından console.log
erişmek yerine ikincisinin başarısız olduğunu unutmayın a
.
window
)window
Nesne çok özelliklere sahip darmadağın olur. Mümkün olduğunda, karmaşa eklememenizi şiddetle öneririz. Bunun yerine, sembollerinizi küçük bir pakete sarın ve nesneye en fazla bir sembol verin window
. (Sık sık nesneye herhangi bir sembol window
vermezim.) Sembollerinizi içermek için tüm kodlarınızı içeren bir işlev kullanabilirsiniz ve isterseniz bu işlev anonim olabilir:
(function() {
var a = 0; // `a` is NOT a property of `window` now
function foo() {
alert(a); // Alerts "0", because `foo` can access `a`
}
})();
Bu örnekte, bir işlevi tanımlarız ve hemen çalıştırırız ( ()
sonunda).
Bu şekilde kullanılan bir işleve genellikle kapsam belirleme işlevi denir . Kapsam belirleme işlevinde tanımlanan işlevler, kapsam belirleme işlevinde tanımlanan değişkenlere erişebilir, çünkü bunlar bu veriler üzerinde kapanır (bkz: Anemik küçük blogumda kapaklar karmaşık değildir ).
window['a']=0
o ben bir harita olarak pencereyi kullanıyorum temizlemek için? window
bazı tarayıcılar buna izin vermeyecek ve beni kullanmaya zorlayacak şekilde özel window.a
mi?
window.a = 0;
sadece tarayıcı ortamlarında ve sadece kurallarla çalışır. Adlı bir değişkene küresel nesne Bağlama window
ES Spec değil ve süre böylece, örneğin, V8 veya node.js için, işe yaramaz this.a = 0;
(küresel yürütme bağlamında çağrıldığında) Spec beri herhangi bir ortamda çalışacak gelmez belirtmek olması gerektiğini bir küresel nesne. Kodunuzu Konu dışı bölümünde olduğu gibi bir IIFE'ye sarıyorsanız , genel nesneye doğrudan başvuru almak veya this
adlandırılmış bir parametre olarak iletebilirsiniz . window
global
var a = 0;
otomatik olarak global nesnenin bir özelliği haline gelir. var b = 0;
Bir fonksiyon bildirimi içinde beyan edersem , temeldeki bazı nesnelerin de özelliği olur mu?
Basit tutmak:
a = 0
Yukarıdaki kod bir global kapsam değişkeni verir
var a = 0;
Bu kod, geçerli kapsamda ve altında kullanılacak bir değişken verecektir
window.a = 0;
Bu genellikle global değişkenle aynıdır.
a
altında geçerli kapsam. Yapabilirsin. Ayrıca, "global değişken" kullanımınız biraz kapalı - "global değişken" dediğiniz iki yer, söylemediğiniz yerden daha küresel değil.
<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
Varsayılan olarak tüm değişkenlerin askıda bırakıldığı global bir nesne var mı? örneğin: 'globals.noVar bildirimi'
window.*
Beyannameyi kullanmak için kesin kılavuz . Bu bildirim, kodunuzun kopyalanmasına karşı en güvenli görünüme sahiptir ve ayrıca temizlenir.
TJ Crowder'ın mükemmel cevabına dayanarak : ( Konu dışı:window
Karışıklıktan kaçının )
Bu onun fikrinin bir örneğidir:
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 ( Bu yanıta göre )
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);
İşte plnkr . Umarım yardımcı olur!
Küresel kapsamda anlamsal bir fark yoktur.
Ancak a=0
kayıt dışı bir değişken için bir değer ayarladığınızdan gerçekten kaçınmalısınız .
Ayrıca global kapsamı düzenlemekten kaçınmak için kapaklar kullanın
(function() {
// do stuff locally
// Hoist something to global scope
window.someGlobal = someLocal
}());
Mutlaka gerekli olduğunda daima kapakları kullanın ve daima küresel kapsamda kaldırın. Zaten iletişiminizin çoğu için eşzamansız olay işleme kullanıyor olmalısınız.
@AvianMoncellor'un belirttiği gibi bir IE hatası var var a = foo
sadece dosya kapsamı için bir global bildiriyor . Bu IE'nin kötü şöhretli kırık tercümanı ile ilgili bir sorundur. Bu hata tanıdık geliyor, bu yüzden muhtemelen doğrudur.
Öyleyse sadık kal window.globalName = someLocalpointer
delete
bir var
).
var
. Bunlar sadece aynı pratik sonuca sahip tamamen farklı mekanizmalar. :-)
var
atladığını söylemeyi unuttum .