javascript的做用域

畢業了最近在找工做,面試一家公司遇到了許多javascript的題,由於只是之前稍微瞭解了一點,遇到了一些之前沒接觸的東西。許多的面試題裏面會有讀程序的題,當時不會作回來一搜發現這些題都是在考js的做用域。javascript

1、JavaScript做用域html

JavaScript變量實際上只有兩種做用域,全局變量和函數的內部變量。在函數內部任何一個地方定義的變量(var scope)其做用域都是整個函數體。
全局變量:指的是window對象下的對象屬性。
做用域劃分:基於上下文,以函數進行劃分的,而不是由塊劃分的。
強調兩點:
1. 在同一做用域中,JavaScript是容許變量的重複定義,而且後一個定義將覆蓋前一個定義。
2. 函數內部若是不加關鍵字var而定義的變量,默認爲全局變量。java

var scope="global"; 
function t(){ 
  console.log(scope); //"global" 
  scope="local"
  console.log(scope); //"local" 
} 
t(); 
console.log(scope); //"local" 
 
 
 
 
var scope="global"; 
function t(){ 
  console.log(scope); //"undefined" 
  var scope="local"
  console.log(scope); //"local" 
} 
t(); 
console.log(scope); //"global"

在變量解析過程當中首先查找局部的做用域,而後查找上層做用域。在第一段代碼的函數當中沒有定義變量scope,因而查找上層做用域(全局做用域),進而進行輸出其值。可是在第二段代碼的函數內定義了變量scope(不管是在console以後仍是以前定義變量,都認爲在此做用域擁有變量scope),因而再也不向上層的做用域進行查找,直接輸出scope。可是不幸的是此時的局部變量i並無賦值,因此輸出的是undefined。面試

//因此根據函數做用域的意思,能夠將上述第二段代碼重寫以下: 
var scope="global"; 
function t(){ 
  var scope; 
  console.log(scope); //「local」
  scope="local"
  console.log(scope); //「local」
} 
t();

因爲函數做用域的特性,局部變量在整個函數體始終是由定義的,咱們能夠將變量聲明」提早「到函數體頂部。數組

var b; //第1步 
function fun(){  
  b = "change";  
}  
alert(b);//輸出undefined,因爲第1步只定義未賦值 
  
  
var b; //第1步 
function fun(){  
  b = "change";  
} 
fun(); //調用上述函數 
alert(b); //輸出change

當使用var聲明一個變量時,建立的這個屬性是不可配置的,也就是說沒法經過delete運算符刪除。
2、做用域實例閉包

<html> 
<head> 
  <script type="text/javascript"> 
    function buttonInit(){ 
      for(var i=1;i<4;i++){ 
        var b=document.getElementById("button"+i); 
        b.addEventListener("click",function(){ alert("Button"+i);},false); 
      } 
    } 
    window.onload=buttonInit; 
  </script> 
</head> 
<body> 
  <button id="button1">Button1</button> 
  <button id="button2">Button2</button> 
  <button id="button3">Button3</button> 
</body> 
</html>

依次彈出button1,button2,button3,當註冊事件結束後,i的值爲4,當點擊按鈕時,事件函數即function(){ alert("Button"+i);}這個匿名函數中沒有i,根據做用域鏈,因此到buttonInit函數中找,此時i的值爲4,因此彈出」button4「。函數

3、利用js閉包實現循環綁定事件this

<html> 
<head> 
  <title>閉包</title> 
</head> 
<body> 
  <ul id="list"> 
    <li>第1條記錄</li> 
    <li>第2條記錄</li> 
    <li>第3條記錄</li> 
    <li>第4條記錄</li> 
    <li>第5條記錄</li> 
    <li>第6條記錄</li> 
  </ul> 
  <script type="text/javascript"> 
    function tt(nob) { 
      this.clickFunc = function() { 
        alert("這是第" + (nob + 1) + "記錄"); 
      } 
    } 
    var list_obj = document.getElementById("list").getElementsByTagName("li"); //獲取list下面的全部li的對象數組 
    for (var i = 0; i<= list_obj.length; i++){ 
      console.log(list_obj[i]) 
      list_obj[i].onmousemove = function(){ 
        this.style.backgroundColor = "#cdcdcd"; 
      } 
      list_obj[i].onmouseout = function() { 
        this.style.backgroundColor = "#FFFFFF"; 
      } 
      //list_obj[i].onclick = function() { 
      // alert("這是第" + i + "記錄"); //不能正常獲取 alert出來的都是:「這是第6記錄」 
      //} 
      var col = new tt(i); //調用tt函數 
      list_obj[i].onclick = col.clickFunc; //執行clickFunc函數 
    } 
  </script> 
</body> 
</html>

這裏的for循環中一開始就會循環完畢,若是不是經過tt()傳入的nob記錄的話,就不能正常獲取alert出來的數。code

相關文章
相關標籤/搜索