js-闭包(权威指南版)


//1,闭包是词法作用域(作用域在定义时决定,不是在调用时决定)
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
};
var r = checkscope()();
console.log(r);//local scope


//2,闭包可以捕捉到单个函数调用的局部变量,并将这些局部变量用做私有状态。
var uniqueInteger = (function(){
                        var counter = 0;
                        return function(){
                            return counter++;
                        }
                    }());
//分析:这是一个嵌套的函数。当外部函数返回之后,其它任何代码都无法访问counter变量,只有内部的函数才能访问它。

//引申1:
function counter(){
    var n = 0;
    return {
        count:function(){return n++;},
        reset:function(){n=0;}
    };
}
var c = counter(), d = counter();
console.log(c.count());//0
console.log(d.count());//0
console.log(c.reset());
console.log(c.count());//0
console.log(d.count());//1
/*
批注:每次调用counter(),都会创建一个新的作用域链和一个新的私有变量。因此,如果调用counter()两次,则会得到两个计算器对象,而且彼此包含不同的私有变量,调用其中一个计数器对象的count()和reset()不会影响到另外一个对象。
*/


//引申2:
function counter(n){
    return {
        get count(){return n++;},
        set count(m){
            if(m >= n) n=m;
            else throw Error("只能越来越大,不能越来越小");
        }
    };
}
var c = counter(1000);
console.log(c.count);//1000
console.log(c.count);//1001
c.count = 2000;
console.log(c.count);//2000
c.count = 2000;//Error
/*
批注:这个版本并未声明局部变量,只是使用参数n来保存私有状态,属性存取器方法可以访问n,这样的话,调用counter()的函数就可以制定私有变量的初始值了。
*/


function constfuncs(){
    var funcs = [];
    for(var i= 0; i<10; i++){
        funcs[i] = function(){
            return i;
        };
    }
    return funcs;
}
var funcs = constfuncs();
console.log(funcs[5]());//10
/*批注,这些闭包都是在同一个函数调用中定义的,因此他们可以共享变量i。
所有的闭包都共享这一个值,因此数组中的函数的返回值都是同一个值,这不是我们想要的结果。
*/

//还有注意this的关键字,而不是变量。每个函数调用都包含一个this值,如果闭包在外部函数里是无法访问this的,除非外部函数将this转存为一个变量:
var self = this;//将this保存至一个变量中,以便嵌套的函数能够访问它。


发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>