Javascript 教程 在线

535JavaScript闭包

闭包就是在提供了一个在外部访问另一个函数内部局部变量的方式。

var add = (function(){
    var count = 0;//外部访问的计数器,局部变量.
    var fun = function(){
        return ++count;
    }
    return fun;
})();
    
    //还可以这样写
    var add2 = (function(){
        var count = 0;//外部访问的计数器,局部变量.
        function plus(){
            return ++count;
    }
    return plus;
})();
    
//还可以这样写
var add3 = (function(){
    var count = 0;//外部访问的计数器,局部变量.
    return function(){
        return ++count;
    }
})();

534JavaScript闭包

理解闭包可以将以上代码分解如下:

function outerFunction() {
    var counter = 0;
    function innerFunction(){
        return counter += 1;
    }
    return innerFunction;
    /*
     注意 typeof innerFunction 是:function;而typeof innerFunction()是number;
    */
}
var add = outerFunction();

/* 
调用 outerFunction()返回的是内部函数innerFucntion,那么调用几次add()将调用几次
内部函数inner Function,内部函数公用了counter,所以能够计数,所以说闭包就是将内部嵌套函数变成外部可调用的。
*/

add();
add();
add();

533JavaScript闭包

我猜想可能很多人看到最后这个计数器问题都会感到困惑, 我也一样。

经过代码验证, 发现其中的奥妙在于:

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

注意: 为什么上面这段代码没有直接写的 function add (){...} 而是把function赋值给了变量add呢?

我们通常会想当然的认为每次调用 add() 都会重走一遍add()中的代码块, 但其实不然。

注意add方法中的return, 它return的并不是1,2,3这样的数值,而是return了一个方法,并且把这个方法赋值给了add变量。

那么在这个function自运行一遍之后,其实最后赋值给add的是return counter += 1 这段代码。

所以后面每次调用add() 其实都是在调用return counter += 1。

再结合文章之前所说的, 闭包会持有父方法的局部变量并且不会随父方法销毁而销毁, 所以这个counter其实就是来自于第一次function执行时创建的变量。

我写了一段demo如下

var tempFunc;
var add = (function () {
    var counter = 0;
    tempFunc = function () { return counter += 1; }
    return tempFunc
})();
function myFunction() {
    console.log("add === tempFunc : " + (add === tempFunc))
    document.getElementById("addOneS").innerHTML = add();
}

532JavaScript闭包

我按我的理解总结下JavaScript闭包吧:

闭包就是一个函数引用另一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会增加内存消耗。

或者说闭包就是子函数可以使用父函数的局部变量,还有父函数的参数。

531JavaScript函数调用

作为函数方法调用函数时,此函数执行了相当于 java 中静态函数的功能。

<script>
var myObject, myArray;
myObject={
    name: "hahaha ",
    hsk: "en"
};
function myFunction(a, b) {
    alert(this);
    return this.name +this.hsk;
}
myArray = [10, 2]
myObject = myFunction.apply(myObject, myArray);       
document.getElementById("demo").innerHTML = myObject; 
</script>

尝试一下 »

可以用的频率较高的函数作这样的设置,为对象执行相关操作。