李志成的个人网站
  • 博客
  • 关于
  • 音乐
  • Rss
首页javascript学习Javascript闭包

学习Javascript闭包

发表于2019-01-16 15:31:16分类于javascript0条评论阅读次数247

在javascript中,存在着两种作用域:全局变量和局部变量。其中在函数中,可以直接读取全局变量。

var i = 0;
function test(){
    console.log(i)
}
test(); // output 0

另外呢就是,变量在函数内声明,变量为局部作用域。局部变量:只能在函数内部访问。

function test(){
    var i = 1
}
console.log(i); // output undefined

如果函数内部不用 var 对变量进行定义,则该变量就会被声明为全局变量;同时在 html 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。

function test(){
    i = 1
}
console.log(i); // output 1

在充分了解变量作用域后,下面就开始理解闭包:

闭包在我的理解是,闭包就是能够调用函数内部变量的函数。

var inc;
function calc(i) {
    var j = 2;
    inc = function() {
        j++;
    };
    var sum = function() {
        return i + j;
    };
    return sum;
}
// 当我们调用calc函数时,将会再返回一个匿名的求和函数。
var f = calc(1); // function sum()
// 当调用函数f时,得到真正计算求和的结果:
f();    // output 3
// 调用一个自增函数,用于自增
inc();
// 当调再次用函数f时:
f();    // output 4

在这个例子中,我们会发现这个结果并没有被立即返回,而是返回了一个函数。直到调用了 f() 后才得到结果。

在这段代码中,f实际上就是闭包sum函数。在分别执行f两次后输出了,3 和 4 的结果。说明了局部变量 i 和 j 一直存在于内存之中,并没有在调用函数后自动删除!

产生这种情况的原因是:

对于 sum 函数来说,j 就是一个全局变量,这将会影响j一直在内存中,而 calc 函数,本身也在内存中,所有,并没有触发浏览器的内存回收机制。从而内存没有被释放!

使用闭包的基本用途:

创建立即函数,锁定变量值,解决变量变化以及函数异步问题:

for (var i=1; i<=3; i++) {
    (function (n) {
        setTimeout(function(){
            console.log(n);
        })
    })(i);
}

变量私有化:

function calc(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;
        }
    }
}
var c1 = calc();
c1.inc(); // 1
c1.inc(); // 2

在返回的对象中,实现了一个 inc 闭包函数,在闭包中携带了一个 x 的局部变量,外部无法直接访问 x 。也就是说把x变量给隐藏起来,不允许外界进行访问。从而达到了变量的私有化。

使用闭包注意的问题:

在闭包中避免引用后续会继续发生变化的变量。

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            console.log(i);
        });
    }
    return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // output 4
f2(); // output 4
f3(); // output 4

为什么结果都是4呢?,原因是函数延迟执行了,当循环循环结束时,i的值为4。而函数引用了i变量。导致函数执行结果都是4。

避免滥用闭包。

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以谨慎使用闭包,同时在退出函数时尽可能释放局部变量,否则可能会导致网页的性能问题。

--发表评论--

🚀support markdown (* ̄▽ ̄*)ブ