1. 程式人生 > >談論javascript閉包

談論javascript閉包

影響 內存占用 被調用 指定 很多 引用 閉包 post gpo

閉包看似很簡單,其實牽扯了很多東西,例如:上下文作用域、內存占用、局部以及全局變量等

function init() {
    var name = "Mozilla"; // name 是一個被 init 創建的局部變量
    function displayName() { // displayName() 是內部函數,一個閉包
        alert(name); // 使用了父函數中聲明的變量
    }
    displayName();
}
init();

init是外部函數,name是外部變量。

displayName屬於內部函數調用時使用的是父函數(init()

)的聲明的變量。

嵌套的函數可以訪問在其外部聲明的變量,簡而言之就是內部函數可以訪問外部函數。


下面的例子也解釋了作用域對變量的影響,請看如下:

function init() {
    var name = "Mozilla"; // name 是一個被 init 創建的局部變量
    function displayName() { // displayName() 是內部函數,一個閉包
        var name = "6666";
        alert(name); // 使用了父函數中聲明的變量
    }
    displayName();
}
init();

上下文作用域,同名變量局部作用域最大。


function makeFunc() {
    var name = "Mozilla";

    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();

JavaScript中的函數會形成閉包。 閉包是由函數以及創建該函數的詞法環境組合而成。這個環境包含了這個閉包創建時所能訪問的所有局部變量。在我們的例子中,

myFunc

是執行 makeFunc 時創建的 displayName 函數實例的引用,而 displayName 實例仍可訪問其詞法作用域中的變量,即可以訪問到 name

由此,當 myFunc 被調用時,name 仍可被訪問,其值 Mozilla 就被傳遞到alert中。


function makeAdder(x) {
    return function(y) {
        console.log(‘:‘ + x);
        return x + y;
    };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2)); // 7
console.log(add10(2)); // 12

在這個示例中,我們定義了 makeAdder(x) 函數,他接受一個參數 x ,並返回一個新的函數。返回的函數接受一個參數 y,並返回x+y的值。

從本質上講,makeAdder 是一個函數工廠 — 他創建了將指定的值和它的參數相加求和的函數。在上面的示例中,我們使用函數工廠創建了兩個新函數 — 一個將其參數和 5 求和,另一個和 10 求和。

add5add10 都是閉包。它們共享相同的函數定義,但是保存了不同的詞法環境。在 add5的環境中,x 為 5。而在 add10 中,x 則為 10。

未完待續。。。

談論javascript閉包