js做用域鏈

1. 執行上下文環境及做用域前端

(1)執行上下文:執行上下文的定義---在執行代碼以前,把將要用到的變量都事先拿出來,有的直接賦值了(this和函數聲明),有的先用undefined佔個位(變量和函數表達式)。web

處於活動狀態的執行上下文環境只有一個。函數每被調用一次,都會產生一個新的執行上下文環境。當執行流進入一個函數時,這個函數的環境就會被推入一個環境棧中。在函數執行以後,環境棧將其環境彈出。即函數執行完以後就會將其執行上下文環境銷燬(還有種狀況就是閉包,閉包執行完以後,他的執行上下文環境不會被銷燬)瀏覽器

(2)全局執行環境 是最外圍的一個執行環境,在web瀏覽器中,全局執行環境是window對象。閉包

(3)做用域:函數在定義的時候,就已經肯定了函數體內部自由變量的做用域。js沒有塊及做用域,除了全局做用域外,只有函數才能建立做用域。做用域最大的用處就是隔離變量,不一樣做用域下同名變量不會有衝突。函數

(4)做用域鏈:做用域有上下級關係,上下級關係的肯定就看函數在哪一個做用域下建立的,當代碼在一個環境中執行,會建立變量對象的一個做用域鏈。當訪問變量時,會一級一級向上尋找變量定義,直到找到他。若一直尋找到全局做用域還找不到就會報 'xxx is not defined'的錯誤。ui

做用域鏈的用途是保證對執行環境有權訪問的全部變量和函數的有序訪問。例:this

var num = 1;

function changeNum(){
   if(num===1){ // 能夠在函數內部訪問num,是由於能夠再做用域鏈中找到他
      num=2;
  } else{
      num=1;
  }
}

changNum();

alert(num) // 2

局部環境中開始時會先在本身的變量對象中搜索變量名和函數名,搜索不到的話就搜索上一級做用域鏈。url

2. 延長做用域鏈spa

try catch語句的catch塊;with語句,這兩個語句會在做用域鏈的前端添加一個變量對象。debug

function buildUrl() { 
 var qs = "?debug=true"; 
 with(location){ 
 var url = href + qs; 
 } 
 return url; 
} 

with 語句接收的是 location 對象,所以其變量對象中就包含了 location 對象的全部屬性和方法,而這個變量對象被添加到了做用域鏈的前端。

with 語句中引用變量 href 時(實際引用的是 location.href),with 語句內部,定義了一個名爲 url 的變量,於是 url 就成了函數執行環境的一部分,因此能夠做爲函數的值被返回。

3. 沒有塊級做用域

js有做用域,函數做用域,可是沒有塊級做用域。js除了全局做用域外,只有函數能建立做用域

if 語句 for語句 中的變量聲明會將變量添加到當前的執行環境

(1)聲明變量

使用 var 聲明的變量會自動被添加到最接近的環境中。若是初始化變量,沒有用var聲明,該變量會自動被添加到全局環境中。

function add(num1, num2) { 
 var sum = num1 + num2; // 這裏若是有var聲明則是被添加到函數內部執行環境中,因此後面訪問不到
 return sum; 
} 
var result = add(10, 20); //30 
alert(sum); //因爲 sum 不是有效的變量,所以會致使錯誤

function add(num1, num2) { 
 sum = num1 + num2; // 這裏沒有用var聲明,sum變量被添加到全局做用域,因此後面能夠訪問到sum的值
 return sum; 
} 
var result = add(10, 20); //30 
alert(sum); //30

(2)查詢標識符

當在某個環境中爲了讀取或寫入而引用一個標識符時,必須經過搜索來肯定該標識符實際表明什麼。搜索過程從做用域鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。若是在局部環境中找到了該標識符,搜索過程中止,變量就緒。若是在局部環境中沒有找到該變量名,則繼續沿做用域鏈向上搜索。搜索過程將一直追溯到全局環境的變量對象。若是在全局環境中也沒有找到這個標識符,則意味着該變量還沒有聲明。

相關文章
相關標籤/搜索