閉包是一個能訪問外部函數定義的變量的函數。javascript
爲何?java
當訪問一個變量時,解釋器會首先在當前做用域查找標示符,若是沒有找到,就去父做用域找,直到找到該變量的標示符或者再也不存在父做用域了,這就是做用域鏈。閉包
做用域鏈的頂端是全局對象。函數
var color = 'blue' function getColor() { // 當前做用域不存在 color,父做用域是全局做用域 return color } getColor() // 'blue'
var color = 'blue' function getColor() { // 當前做用域存在 color var color = 'red' return color } getColor() // 'red'
在看個增強版的demo。閉包能修改外部函數定義的變量。spa
function createCounter(initial) { var counter = initial; function increment(value) { counter += value; } function get() { return counter; } return { increment: increment, get: get }; } var myCounter1 = createCounter(100); var myCounter2 = createCounter(200); myCounter1.get(); // 100 myCounter2.get(); // 200 myCounter1.increment(2); myCounter2.increment(5); myCounter1.get() // 102 myCounter2.get() // 205
以下圖myCounter1.get和myCounter2.get的函數對象擁有着同樣的代碼以及同樣的屬性值(name,length等等),可是它們的[[scope]]指向的是不同的做用域對象