一、執行上下文閉包
在一段script 或者一個函數做用域中 都會生成一個執行上下文app
在全局執行上下文中 js會將 變量 與 函數聲明提取出來函數
在函數執行上下文中 在函數執行以前 會將函數內的變量定義 函數聲明 this arguments 提取出來this
二、this指向spa
做爲構造函數執行指針
做爲對象屬性執行code
普通函數執行對象
call apply bind 方式執行blog
this只有在執行時纔會改變指針 定義時this不會指向任何對象 js是解釋型語言不是定義型ip
三、做用域鏈
函數做用域鏈與this偏偏相反 this是隻有在執行時候確認 而做用域鏈是函數在定義時就已經肯定了
自由變量 當前函數沒有定義的變量叫作自由變量 官方解釋: 閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即便已經離開了創造它的環境也不例外 上一段代碼解釋閉包
<script> function fn1(){ var a = 10 return function(){ return a } } var a = 100 var fn = fn1() console.log(fn) console.log(fn()) </script>
上面輸出結果是10 也就是說 函數定義的時候其做用域鏈就已經固定 而且 函數定義時 它的做用域和引用的自由變量就已經固定 不管這個函數 在任何位置引用 調用它內部的自有變量都不會再改變了 理論上說任何一個函數都是一個閉包 那麼閉包主要的應用場景就是 保護變量 返回函數 傳入函數
function fn1(){ var a = 10 return function(){ return a } } var fn = fn1() function fn2 (fn){ var a = 1000 console.log(fn()) } fn2(fn)
輸出結果仍然是10 不管任何環境閉包的做用域和自由變量都已經定死了 下面舉兩個簡單的閉包案例
<script> for(var i = 0; i < 10 ; i++){ (function(i){ var a = document.createElement('a') a.innerHTML = i + '<br/>' a.onclick = function(){ alert(i) } document.body.appendChild(a) })(i) } </script>
上面每次執行咱們都建立了一個獨立的自執行函數 而後將 i 傳入 這個時候自執行函數會將 i 變量固定的保存下來 下面舉一個變量權限的例子
function firstIndex(){ var _list = [] return function(id){ if(_list.indexOf(id) >= 0 ){ return false }else{ _list.push(id) return true } } } var fn = firstIndex() console.log(fn(10)) console.log(fn(10)) console.log(fn(20))