Javascript işlevi kapsam belirleme ve kaldırma


91

Ben Cherry'nin JavaScript Kapsam Belirleme ve Kaldırma hakkında şu örneği verdiği harika bir makale okudum :

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);

Yukarıdaki kodu kullanarak, tarayıcı "1" i uyaracaktır.

Hala neden "1" döndürdüğünden emin değilim. Söylediği bazı şeyler akla gelir: Tüm fonksiyon beyanları en üste çıkar. Fonksiyonu kullanarak bir değişkenin kapsamını değiştirebilirsiniz. Hala benim için tıklamıyor.

Yanıtlar:


122

İşlev kaldırma, işlevlerin kapsamlarının en üstüne taşınması anlamına gelir. Yani,

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 

tercüman tarafından buna yeniden yazılacak

function b() {
  function a() {}
  a = 10;
  return;
}

Tuhaf değil mi?

Ayrıca, bu durumda,

function a() {}

aynı şekilde davrandı

var a = function () {};

Yani, özünde, kodun yaptığı şu:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"

2
Yani tüm fonksiyon bildirimleri sonunda bir değişkene mi atanır?
dev.e.loper

15
@ dev.e.loper Evet, Javascript'te işlevler tıpkı dizeler ve sayılar gibi birinci sınıf nesnelerdir. Bu, değişkenler olarak tanımlandıkları ve diğer işlevlere aktarılabilecekleri, dizilerde saklanabilecekleri vb. Anlamına gelir.
Peter Olson

4
İşlev gövdesi hiçbir şekilde "yeniden yazılmaz". Çeşitli ECMAScript standartları, değişken ve işlev bildirimlerinin kod yürütme başlamadan önce işlendiğini açıkça belirtir. Yani, hiçbir şey hareket ettirilmez , bu yürütme emriyle ilgilidir (bu nedenle, hareket veya yeniden düzenlemeye neden olan "kaldırma" teriminden hoşlanmam). Yeniden yazılan kodunuzda, bildirim var aişlev bildiriminden önce ve atama a = 1sonra olmalıdır. Ancak bunun aslında ayrıştırıcı, belirteç oluşturucu, yorumlayıcı, derleyici, her neyse, bunun sadece bir eşdeğer tarafından gerçekleşeceği belirtilmediğini unutmayın .
RobG

3
@RobG Elbette, sanırım tanıma küçük bir "çocuklara yalan" diyebilirsiniz , ancak sonuçta davranış aynıdır, kod tam anlamıyla yeniden düzenlenir veya sadece yürütme sırası yeniden düzenlenir. Perde arkasında gerçekte olan şey daha çok akademik bir kaygıdır ve hatta uygulamaya bağlı olabilir.
Peter Olson

7
"Ayrıca, bu örnekte, function a() {}aynı şekilde davrandı var a = function () {};"  - bu iki yönden yanlıştır: birincisi, eğer bir şey olursa, olurdu var a = function a() {};(işlev aslında anonim değildir), ikincisi, bu iki biçim birbirinin yerine geçemez, çünkü var a = function a() {};sadece var a;kısmı kaldırılırdı. a = function a() {};Bölümü hala dönüş deyimi arkasında olurdu. Orijinal biçim bir işlev bildirimi olduğundan ve bir işlev ifadesi olmadığından, aslında bir bütün olarak kaldırılır.
Sebastian Simon

6

Hatırlamanız gereken şey, tüm işlevi ayrıştırması ve çalıştırmadan önce tüm değişken bildirimlerini çözmesidir. Yani....

function a() {} 

gerçekten olur

var a = function () {}

var a onu yerel bir kapsama zorlar ve değişken kapsamı tüm fonksiyon boyunca olur, bu nedenle global a değişkeni hala 1'dir, çünkü onu bir fonksiyon yaparak yerel bir kapsamda tanımlamışsınızdır.


5

İşlev a, içeriden kaldırılır b:

var a = 1; 
function b() { 
   function a() {} 
   a = 10; 
   return;
} 
b(); 
alert(a);

neredeyse kullanmak gibi olan var:

var a = 1; 
function b() { 
   var a = function () {};
   a = 10; 
   return;
} 
b(); 
alert(a);

İşlev yerel olarak bildirilir ve ayar ayalnızca yerel kapsamda gerçekleşir, genel var.


1
bu satır "var a = function () {};" her şeyi açıklığa kavuşturuyor .. temelde JavaScript dinamik bir dildir ve "function" da JavaScript'te bir nesnedir.
refactor

3
  1. işlev bildirimi function a(){}önce kaldırılır ve şu şekilde davranır var a = function () {};, dolayısıyla yerel kapsamda aoluşturulur.
  2. Aynı isimli iki değişkeniniz varsa (biri globalde diğeri yerelde), yerel değişken her zaman global değişkene göre önceliklidir.
  3. Ayarladığınızda a=10, aglobal değişkeni değil yerel değişkeni ayarlıyorsunuz .

Bu nedenle, global değişkenin değeri aynı kalır ve 1 uyarı alırsınız


1

function a() { }işleve ayerel bir değişken oluşturan bir işlev ifadesidir b.
Değişkenler, bir işlev çözümlendiğinde, varveya işlev deyiminin çalıştırılıp çalıştırılmadığına bakılmaksızın oluşturulur .

a = 10 bu yerel değişkeni ayarlar.


siz eklemediğiniz sürece (bu yönergeyi destekleyen ortamlarda) işlev çalıştırıldığında aslında genel kapsamda a = 10bir değişken belirler . b"use strict"
Sean Vieira

@Sean: Hayır, çünkü işlev ifadesi yerel bir tanımlayıcı yaratır.
SLaks

... ve .... haklısın. Fonksiyon kaldırmanın o özel sonucunu fark etmemiştim. Teşekkürler!
Sean Vieira

1

Bu küçük kod parçacığındaki çekişme noktası nedir?

Dava 1:

Aşağıdaki gibi function a(){}gövdesinin içine tanımı ekleyin function b.logs value of a = 1

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

Durum 2

Aşağıdaki gibi function a(){}gövde içindeki tanımı hariç tutun function b.logs value of a = 10

var a = 1;
function b() {
  a = 10;  // overwrites the value of global 'var a'
  return;
}
b();
console.log(a); // logs a = 10

Gözlem, ifadenin console.log(a)aşağıdaki değerleri kaydettiğini anlamanıza yardımcı olacaktır .

Durum 1: a = 1

Durum 2: a = 10

Varsayar

  1. var a genel kapsamda sözcüksel olarak tanımlanmış ve ilan edilmiştir.
  2. a=10 Bu ifade, değeri 10'a yeniden atıyor, sözcüksel olarak b işlevinin içinde yer alıyor.

Her iki durumun açıklaması

Çünkü function definition with name propertya ile aynıdır variable a. variable aİçeride function body byerel bir değişken haline gelir. Önceki satır, a'nın global değerinin bozulmadan kaldığı ve a'nın yerel değerinin 10'a güncellendiği anlamına gelir.

Yani, söylemek istediğimiz şey aşağıdaki kodun

var a = 1;
function b() {
  a = 10;
  return;

  function a() {}
}
b();
console.log(a); // logs a = 1

JS yorumlayıcısı tarafından aşağıdaki şekilde yorumlanır.

var a = 1;
function b() {
  function a() {}
  a = 10;
  return;


}
b();
console.log(a); // logs a = 1

Kaldırabileceğimiz Ancak, function a(){} definition, value of 'a'beyan ve fonksiyon b dışında tanımlanmış, bu değer üzerine yazılır alır ve onu çünkü değeri üzerine yazılır geçirmesi durumunda 2. 10'a kadar değişir a=10küresel bildiriye atıfta ve yerel olarak ilan edilmesi olsaydı biz sahip olmalıdır yazılı var a = 10;.

var a = 1;
function b() {
  var a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;
}
b();
console.log(a); // logs a = 1

Biz değiştirerek bizim şüphe daha da netleştirmek için name propertyin function a(){} definitiondiğer bazı isim daha hiç'a'

var a = 1;
function b() {
  a = 10; // here var a is declared and defined locally because it uses a var keyword. 
  return;

  function foo() {}
}
b();
console.log(a); // logs a = 1

1

Kaldırma, anlamayı kolaylaştırmak için bizim için yapılmış bir kavramdır. Gerçekte olan şey, bildirimler ilk önce kapsamlarına göre yapılır ve atamalar bundan sonra gerçekleşir (aynı anda değil).

Bildirimler gerçekleştiğinde, var ao zaman function bve bu bkapsamın içinde function ailan edilir.

Bu fonksiyon a, genel kapsamdan gelen a değişkenini gölgeleyecektir.

Bildirimler yapıldıktan sonra atanan değerler başlayacak, global adeğeri alacak 1ve a içi function balacaktır 10. bunu yaptığınızda alert(a), gerçek genel kapsam değişkenini çağıracaktır. Koddaki bu küçük değişiklik, daha net hale getirecek

        var a = 1;

    function b() {
        a = 10;
        return a;

        function a() { }
    }

    alert(b());
    alert(a);

1
Codechool.com'daki bir kursta bile bu kadar çok uzmanın, ne olduğuna dair basit bir bakıştan başka bir şey olmayan kaldırma işleminden bahsetmesi ilginçtir, aslında kaldırma hiç olmaz. Ref: 1) developer.mozilla.org/en-US/docs/Glossary/Hoisting 2) Secrets of the JavaScript Ninja 2 / e'nin 5. Bölümü, john resig, bear bebeault, josip maras
adnan2nd

1

Şaşırtıcı bir şekilde, buradaki cevapların hiçbiri Kapsam Zincirindeki Yürütme Bağlamının uygunluğundan bahsetmiyor.

JavaScript Motoru, o anda yürütülmekte olan kodu bir Yürütme Bağlamında sarar. Temel yürütme bağlamı, genel Yürütme Bağlamıdır. Her yeni işlev çağrıldığında, yeni bir Yürütme Bağlamı oluşturulur ve Yürütme Yığını'na yerleştirilir. Diğer programlama dillerinde bir Çağrı Yığını üzerinde oturan bir Yığın Çerçevesi düşünün. Son giren ilk çıkar. Artık her Yürütme Bağlamının JavaScript'te kendi Değişken Ortamı ve Dış Ortamı vardır.

Aşağıdaki örneği bir gösteri olarak kullanacağım.

1) İlk olarak, küresel Yürütme Bağlamının Oluşturma Aşamasına giriyoruz. Sözcüksel Ortamın Hem Dış Çevresi hem de Değişken Ortamı yaratılır. Global Nesne kurulur ve ona işaret eden özel değişken 'this' ile belleğe yerleştirilir. A fonksiyonu ve kodu ve tanımlanmamış bir değere sahip myVar değişkeni, global Değişken Ortamında belleğe yerleştirilir. a'nın kodunun çalıştırılmadığına dikkat etmek önemlidir. Sadece a fonksiyonu ile hafızaya alınır.

2) İkincisi, Yürütme Bağlamının Yürütme Aşamasıdır. myVar artık tanımlanmamış bir değer değil. Global Değişken Ortamında saklanan 1 değeriyle başlatılır. A işlevi çağrılır ve yeni bir Yürütme Bağlamı oluşturulur.

3) a işlevinin Yürütme Bağlamında, kendi Yürütme Bağlamının Oluşturma ve Yürütme Aşamasından geçer. Kendi Dış Ortamı ve Değişken Ortamı, dolayısıyla kendi Sözcüksel Ortamı vardır. B fonksiyonu ve myVar değişkeni Değişken Ortamında saklanır. Bu Değişken Ortam, küresel Değişken Ortamdan farklıdır. A işlevi sözcüksel olarak (fiziksel olarak kodda) küresel Yürütme Bağlamıyla aynı düzeyde bulunduğundan, Dış Ortamı küresel Yürütme Bağlamıdır. Bu nedenle, a işlevi Değişken Ortamında olmayan bir değişkene atıfta bulunacaksa, Kapsam Zincirini arayacak ve değişkeni global Yürütme Bağlamının Değişken Ortamında bulmaya çalışacaktır.

4) b işlevi, a işlevinde çağrılır. Yeni bir Yürütme Bağlamı oluşturulur. Sözcüksel olarak a işlevine oturduğundan, Dış Ortamı a'dır. Dolayısıyla, myVar'a başvurduğunda, myVar işlev b'nin Değişken Ortamında olmadığından, a işlevinin Değişken Ortamına bakacaktır. Orada bulur ve console.log 2. yazdırır. Fakat eğer değişken a'nın Değişken Ortamı işlevinde değilse, o zaman a işlevinin Dış Ortamı genel Yürütme Bağlamı olduğundan, Kapsam Zinciri orada aramaya devam edecektir.

5) b ve a işlevinin yürütülmesi tamamlandıktan sonra, Yürütme Yığınından çıkarılırlar. Tek iş parçacıklı JavaScript Motoru, küresel Yürütme Bağlamında çalışmaya devam eder. B işlevini çağırır. Ancak küresel Değişken Ortamında b işlevi yoktur ve küresel Yürütme Bağlamında aranacak başka bir Dış Ortam yoktur. Böylece JavaScript Engine tarafından bir istisna ortaya çıkar.

function a(){
  function b(){
    console.log(myVar);
  }

  var myVar = 2;
  b();
}

var myVar = 1;
a();
b();
> 2
> Uncaught ReferenceError: b is not defined

Aşağıdaki örnek Kapsam Zincirini iş başında göstermektedir. B fonksiyonunun Yürütme Bağlamının Değişken Ortamında, myVar yoktur. Böylece, a fonksiyonu olan Dış Ortamını arar. A işlevinin de Değişken Ortamında myVar'ı yoktur. Dolayısıyla, Motor aramaları, a'nın Dış Ortamını, yani global Yürütme Bağlamının Dış Ortamı işlevini görür ve myVar burada tanımlanır. Bu nedenle, console.log 1 yazdırır.

function a(){
  function b(){
    console.log(myVar);
  }

  b();
}

var myVar = 1;
a();
> 1

Dış Ortam ve Değişken Ortam dahil, Yürütme Bağlamı ve onunla ilişkili Sözcüksel Ortam ile ilgili olarak, JavaScript'teki değişkenlerin kapsamını etkinleştirin. Aynı işlevi birden çok kez çağırsanız bile, her çağrı için kendi Yürütme Bağlamını oluşturur. Dolayısıyla, her Yürütme Bağlamı, Değişken Ortamında değişkenlerin kendi kopyasına sahip olacaktır. Değişkenlerin paylaşımı yoktur.


0

Değişken adı ile işlev adı "a" anlamına geldiği için oluyor. Bu nedenle, Javascript'in kaldırılması nedeniyle adlandırma çakışmasını çözmeye çalışır ve a = 1 döndürür.

"JavaScript Kaldırma" http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html hakkındaki bu yazıyı okuyana kadar da kafam karışmıştı.

Umarım yardımcı olur.


0

İşte daha fazla açıklama ve birlikte oynayabileceğim yardımcı bir kemanla cevabın özetini burada bulabilirsiniz.

// hoisting_example.js

// top of scope ie. global var a = 1
var a = 1;

// new scope due to js' functional (not block) level scope
function b() {
    a = 10; // if the function 'a' didn't exist in this scope, global a = 10
  return; // the return illustrates that function 'a' is hoisted to top
  function a(){}; // 'a' will be hoisted to top as var a = function(){};
}

// exec 'b' and you would expect to see a = 10 in subsequent alert
// but the interpreter acutally 'hoisted' the function 'a' within 'b' 
// and in doing so, created a new named variable 'a' 
// which is a function within b's scope
b();

// a will alert 1, see comment above
alert(a);

https://jsfiddle.net/adjavaherian/fffpxjx7/


0

scpope & kapatma & kaldırma (var / işlev)

  1. scpope: global var herhangi bir yerden erişilebilir (tüm dosya kapsamı), yerel var sadece yerel kapsam (fonksiyon / blok kapsamı) tarafından erişilebilir!
    Not: bir işlevde var anahtar sözcüklerini kullanmayan yerel bir değişken, küresel bir değişken haline gelecektir!
  2. kapanış: yerel kapsama (ana işlev) ve genel kapsama erişebilen diğer işlevin içindeki bir işlev, ancak bunlara başkaları tarafından erişilemez! sürece, dönüş değeri olarak iade edin!
  3. kaldırma: tüm bildirme / geri alma değişkenlerini / işlevlerini, değeri veya null atamaktan ziyade kapsamın üstüne taşı!
    Not: sadece beyanı taşır, değeri hareket ettirmez!

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined



0

Kaldırma JavaScript'te, değişken bildirimlerinin herhangi bir kod çalıştırılmadan önce program boyunca yürütülmesi anlamına gelir. Bu nedenle, kodun herhangi bir yerinde bir değişken bildirmek, onu başlangıçta bildirmekle eşdeğerdir.


0

Hepsi 'a' değişkeninin kapsamına bağlıdır. Görüntü olarak kapsamları oluşturarak açıklamama izin verin.

Burada JavaScript 3 kapsam oluşturacaktır.

i) Küresel kapsam. ii) İşlev b () kapsamı. iii) Fonksiyon a () kapsamı.

görüntü açıklamasını buraya girin

'Uyarı' yöntem kapsamını çağırdığınızda, bu süre Global'e ait olduğu açıktır, bu nedenle Global kapsamdan yalnızca 1 olan 'a' değişkeninin değerini seçecektir.


0

Uzun Mesaj!

Ama havayı temizleyecek!

Java Script'in çalışma şekli, iki adımlı bir süreç içermesidir:

  1. Derleme (tabiri caizse) - Bu adım, değişkenleri ve işlev bildirimlerini ve bunların ilgili kapsamını kaydeder. Bu değerlendiren işlev ifadesi içermez: var a = function(){}(atama gibi veya değişken ifade 3etmek xdurumunda arasında var x =3;. Hangi bir şey ama RHS kısmının değerlendirilmesi)

  2. Tercüman: Bu, yürütme / değerlendirme kısmıdır.

Anlamak için aşağıdaki kodun çıktısını kontrol edin:

//b() can be called here!
//c() cannot be called.
console.log("a is " + a);
console.log("b is " + b);
console.log("c is " + c);
var a = 1;
console.log("Now, a is " + a);
var c = function() {};
console.log("Now c is " + c);

function b() {
  //cannot write the below line:
  //console.log(e); 
  //since e is not declared.
  e = 10; //Java script interpreter after traversing from this function scope chain to global scope, is unable to find this variable and eventually initialises it with value 10 in global scope.
  console.log("e is " + e) //  works!
  console.log("f is " + f);
  var f = 7;
  console.log("Now f is " + f);
  console.log("d is " + d);
  return;

  function d() {}
}
b();
console.log(a);

Bırakalım şunu:

  1. Derleme aşamasında, 'a' değeri ' undefined' ile küresel kapsam altında kaydedilir . Aynı şey ' c' için de geçerli, şu andaki değeri ' undefined' değil ' function()' olacaktır. ' b' küresel kapsamda bir işlev olarak kaydedilir. İçerinin bkapsamı, fşu anda tanımsız olacak bir değişken olarak kaydedilecek ve ' d' işlevi kaydedilecektir.

  2. Yorumlayıcı çalıştığında, tanımlanmış değişkenlere ve function()(ifadelere değil) yorumlayıcı gerçek ifade satırına ulaşmadan önce erişilebilir. Böylece değişkenler yazdırılır ' undefined' ve anonim işlev daha önce bildirilebilir. Ancak, ifade başlatılmadan önce bildirilmemiş değişkene erişmeye çalışmak aşağıdaki gibi bir hatayla sonuçlanır:

console.log(e)
e = 3;

Şimdi, aynı ada sahip değişken ve işlev bildiriminiz olduğunda ne olur?

Cevap - işlevler her zaman daha önce kaldırılır ve aynı isim değişkeni bildirilirse, yinelenmiş olarak değerlendirilir ve yok sayılır. Unutma, düzen önemli değil. İşlevlere her zaman öncelik verilir. Ancak değerlendirme aşamasında değişken referansını herhangi bir şeye değiştirebilirsiniz (Son atama neyse onu saklar) Aşağıdaki koda bir göz atın:

var a = 1;
console.log("a is " + a);

function b() {
  console.log("a inside the function b is " + a); //interpreter finds                                'a' as function() in current scope. No need to go outside the scope to find 'a'.
  a = 3; //a changed
  console.log("Now a is " + a);
  return;

  function a() {}
}
var a; //treated as duplicate and ignored.
b();
console.log("a is still " + a + " in global scope"); //This is global scope a.


0

Kaldırma, JavaScript'in davranışsal kavramıdır. Kaldırma (hareket ettirme), değişkenlerin nasıl ve nerede bildirilmesi gerektiğini açıklayan bir kavramdır.

JavaScript'te, bir değişken kullanıldıktan sonra bildirilebilir çünkü İşlev bildirimleri ve değişken bildirimleri, JavaScript yorumlayıcısı tarafından her zaman görünmez bir şekilde kapsama alanlarının en üstüne taşınır ("kaldırılır").

Çoğu durumda iki tür kaldırma ile karşılaşıyoruz.

1. Değişken beyanname kaldırma

Bunu bu kod parçasıyla anlayalım.

 a = 5; // Assign 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
 var a; // Declare a
  //output-> 5

Burada a değişkeninin bildirimi, derleme sırasında javascript yorumlayıcısı tarafından görünmez bir şekilde en üstte barındırılacaktır. Böylece a'nın değerini alabildik. Ancak değişkenlerin bu şekilde beyan edilmesi yaklaşımı tavsiye edilmemektedir, çünkü değişkenleri zaten bu şekilde tepeye beyan etmemiz gerekir.

 var a = 5; // Assign and declare 5 to a
 elem = document.getElementById("demo"); // Find an element 
 elem.innerHTML = a;                     // Display a in the element
  // output -> 5

başka bir örnek düşünün.

  function foo() {
     console.log(x)
     var x = 1;
 }

aslında şu şekilde yorumlanır:

  function foo() {
     var x;
     console.log(x)
     x = 1;
  }

Bu durumda x tanımsız olacaktır

Değişken bildirimini içeren kodun çalıştırılmış olması önemli değildir. Bu örneği düşünün.

  function foo() {
     if (false) {
         var a = 1;
     }
     return;
     var b = 1;
  }

Bu işlevin böyle olduğu ortaya çıkıyor.

  function foo() {
      var a, b;
      if (false) {
        a = 1;
     }
     return;
     b = 1;
  }

Değişken bildiriminde, atama değil, yalnızca değişken tanım kaldırılır.

  1. İşlev bildirimi kaldırma

Değişkenin kaldırma hareketinin aksine, işlev gövdesi veya atanan değer de kaldırılacaktır. Bu kodu düşünün

 function demo() {
     foo(); // this will give error because it is variable hoisting
     bar(); // "this will run!" as it is function hoisting
     var foo = function () {
         alert("this would not run!!");
     }
     function bar() { 
         alert("this will run!!");
     }
 }
 demo();

Şimdi hem değişken hem de fonksiyon kaldırmayı anladığımıza göre, şimdi bu kodu anlayalım.

var a = 1;
function b() {
  a = 10;
  return;
   function a() {}
}
b();
alert(a);

Bu kod böyle olacak.

var a = 1;                 //defines "a" in global scope
 function b() {  
   var a = function () {}; //defines "a" in local scope 
    a = 10;                 //overwrites local variable "a"
    return;      
 }       
 b();       
 alert(a); 

A () işlevinin b () içinde yerel kapsamı olacaktır. a (), kodu tanımıyla birlikte yorumlarken (yalnızca fonksiyon kaldırma durumunda) en üste taşınacaktır, bu nedenle a artık yerel kapsama sahip olacak ve bu nedenle a fonksiyonu içinde kendi kapsamına sahip olan a'nın genel kapsamını etkilemeyecektir b () .


0

Bildiğim kadarıyla, kaldırma işlemi değişken bildirimi ve işlev bildirimi ile gerçekleşir, örneğin:

a = 7;
var a;
console.log(a) 

JavaScript motorunun içinde ne olur:

var a;
a = 7;
console.log(a);
// 7

Veya:

console.log(square(7)); // Output: 49
function square(n) { return n * n; }

Olacak:

function square(n) { return n * n; }
console.log(square(7)); // 49

Ancak değişken atama, işlev ifadesi ataması gibi atamalar kaldırılmayacaktır: Örneğin:

console.log(x);
var x = 7; // undefined

Şöyle olabilir:

var x;
console.log(x); // undefined
x = 7;

0

Javascript'te barındırmayı tek bir cümlede tanımlamak değişkenlerdir ve işlevler, bildirildikleri kapsamın en üstüne kaldırılır.

görüntü açıklamasını buraya girin

Kaldırma işlemini doğru bir şekilde anlamak için başlangıçta olduğunuzu varsayıyorum, tanımsız ve ReferenceError arasındaki farkı anladık

 var v;
 console.log(v);
 console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/

şimdi aşağıdaki kodda ne görüyoruz? bir değişken ve bir fonksiyon ifadesi önemsizdir.

<script>
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
</script>

ancak hem değişkenin hem de fonksiyonun oradaki kapsamın üstüne kaldırıldığının kanıtı olan gerçek resim:

console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
      return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));

İlk iki günlüklerinin Çıktı edilir tanımsız ve TypeError: getSum bir işlev değil var hem çünkü totalAmo ve getSum bağırma gibi kendi kapsamı üzerine askıya alır

 <script>
        var totalAmo;
        var getSum;

        console.log(totalAmo);
        console.log(getSum(8,9));
        var totalAmo = 8;
        var getSum = function(a, b){
            return a+b;
        }
        console.log(totalAmo);
        console.log(getSum(9,7));
    </script>

Ancak işlev bildirimi için tüm işlevler kapsamlarının en üstüne kaldırılır.

console.log(getId());
function getId(){
   return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/

Şimdi aynı mantık, işlevsel kapsam içinde açıklanan değişkenler, işlev deneyleri ve işlev tanımları için de geçerli. Kilit nokta: bunlar dosyanın en üstüne kaldırılmayacak ;

function functionScope(){
            var totalAmo;
            var getSum;

            console.log(totalAmo);
            console.log(getSum(8,9));
            var totalAmo = 8;
            var getSum = function(a, b){
                return a+b;
            }
        }

Dolayısıyla, var anahtar sözcüğü, değişken ve işlevi kullandığınızda , kapsamın en üstüne kaldırılır (genel kapsam ve işlev kapsamı). Peki let ve const const ve izin hala küresel kapsam ve var tıpkı fonksiyon kapsamı, ancak const hem farkında ve değişkenler de kapsamını bloke denilen başka kapsamı farkında olsun. for loop, if else deyimi, while döngüsü vb. gibi bir kod bloğu olduğunda bir blok kapsamı mevcuttur.

Const kullandığımızda ve bu blok kapsamında bir değişken bildirmek için izin verdiğimizde, değişken bildirimi yalnızca içinde bulunduğu bloğun üstüne kaldırılacak ve üst işlevin tepesine veya üst işlevin üstüne kaldırılmayacaktır. kaldırıldığı küresel kapsam.

 function getTotal(){
            let total=0;
            for(var i = 0; i<10; i++){
                let valueToAdd = i;
                var multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

Abobe örneğindeki değişkenler aşağıdaki gibi kaldırılacak

 function getTotal(){
            let total;
            var multiplier;
            total = 0;
            for(var i = 0; i<10; i++){
                let valueToAdd;
                valueToAdd = i;
                multiplier = 2;
                total += valueToAdd*multiplier;
            }
            return total;
        }

0

ES5: fonksiyon kaldırma ve değişken kaldırma

function hoistingöncelik greaterşundanvariable hoisting

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2016-06-01
 * @modified
 *
 * @description function-hoisting.js
 * @augments
 * @example
 * @link
 *
 */

(function() {
  const log = console.log;

  var a = 1;
  function b() {
    a = 10;
    log(`local a`, a)
    return;
    // function hoisting priority is greater than variable hoisting
    function a() {}
  }
  b();
  log(`global a`, a);
  // local a 10
  // global a 1
})();



eşittir

(function() {
  const log = console.log;

  // define "a" in global scope
  var a = 1;
  function b() {
    // define "a" in local scope
    var a ;
    // assign function to a
    a = function () {};
    // overwrites local variable "a"
    a = 10;
    log(`local a`, a);
    return;
  }

  b();
  // log global variable "a"
  log(`global a`, a);

  // local a 10
  // global a 1
})();

kaldırmanın arkasındaki sebep

var a = 1;                
//"a" is global scope
function b() {  
   var a = function () {}; 
   //"a" is local scope 
   var x = 12; 
   //"x" is local scope 
   a = 10;
   //global variable "a" was overwrited by the local variable "a"  
   console.log("local a =" + a);
   return console.log("local x = " + x);
}       
b();
// local a =10
// local x = 12
console.log("global a = " + a);
// global a = 1
console.log("can't access local x = \n");
// can't access local x = 
console.log(x);
// ReferenceError: x is not defined

/**
 *  scpope & closure & hoisting (var/function)
 *  
 * 1. scpope : the global var can be access in any place(the whole file scope), local var only can be accessed by the local scope(function/block scope)!
 * Note: if a local variable not using var keywords in a function, it will become a global variable!
 * 
 * 2. closure : a function inner the other function, which can access local scope(parent function) & global scope, howerver it's vars can't be accessed by others! unless, your return it as return value!
 * 
 * 3. hoisting : move all declare/undeclare vars/function to the scope top, than assign the value or null!
 * Note: it just move the declare, not move the value!
 * 
 */

ES6 let, constkaldırma mevcut değil

(() => {
  const log = console.log;
  log(a)
  // Error: Uncaught ReferenceError: Cannot access 'a' before initialization
  let a = 1;
})();



(() => {
  const log = console.log;
  log(b)
  // Error: Uncaught ReferenceError: Cannot access 'b' before initialization
  const b = 1;
})();

referanslar

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.