分享几个闭包的例子

童猛
• 阅读 6866

例子1

  • 立即调用表达式会立即执行,不需要test()调用
  • 显示调用test()只是会调用一个匿名函数
  • 局部变量i不会随着调用的结束而被回收,而是一直保存在内存中
javascriptvar test = (function () {
    console.log("test func");
    var i = 0;
    return function () {
        console.log(i);
        return i++;
    }
})();

console.log("........");
test();     //0
test();     //1
test();     //2

// output
// test func
// ........
// 0
// 1
// 2

例子2

  • test不是立即调用的,需要显示调用test()返回匿名函数的引用,如:var a = test(),这时a指向匿名函数
  • a()调用这个匿名函数,局部变量i对于a来说一直会常驻内存中
  • var b = test(),再次调用test,b会返回一个新的匿名函数的拷贝,并且i对于b也是唯一的
javascriptvar test = function () {
    console.log("test func");
    var i = 0;
    return function () {
        console.log(i);
        return i++;
    }
};

console.log("........");
var a = test();
a();    //0
a();    //1
a();    //2

var b = test()
b();    //0

// output
// ........
// test func
// 0
// 1
// 2
// test func
// 0

例子3

  • 不使用闭包,循环结束后i=3
javascriptvar arr = [1, 2, 3];
var obj = {};

var test = function () {
    for (var i=0; i<arr.length; i++) {
        obj[i] = function () {
            console.log(i);
        };
    }
}

test();

var fn0 = obj[0];
var fn1 = obj[1];
var fn2 = obj[2];

fn0();   //3
fn1();   //3
fn2();   //3
  • 在for循环里创建了一个立即调用函数表达式
  • fn0,fn1,fn2分别指向了匿名函数的引用
  • fn0(),fn1(),fn2()都访问了i(这个i是位于这个匿名函数的上层作用域链,它会被保存在内存中,对于每一个函数引用来说i是唯一的)
javascriptvar arr = [1, 2, 3];
var obj = {};

var test = function () {
    for (var i=0; i<arr.length; i++) {
        (function (i) {
            obj[i] = function () {
                console.log(i);
            };
        })(i);  //i作为参数传给立即调用函数
    }
};

test();

var fn0 = obj[0];
var fn1 = obj[1];
var fn2 = obj[2];

fn0();   //0
fn1();   //1
fn2();   //2
  • 下面这个例子为了加深理解
javascriptvar arr = [1, 2, 3];
var obj = {};

var test = function () {
    for (var i=0; i<arr.length; i++) {
        (function (i) {
            obj[i] = function () {
                console.log(i++);
            };
        })(i);  //i作为参数传给立即调用函数
    }
};

test();

var fn0 = obj[0];
var fn1 = obj[1];
var fn2 = obj[2];

// 两次fn0()访问同一个内存中的i值
fn0();  //0
fn0();  //1

// 两次fn1()访问同一个内存中的i值
fn1();  //1
fn1();  //2

// 两次fn2()访问同一个内存中的i值
fn2();  //2
fn2();  //3

例子4

javascriptvar arr = [1, 2, 3];

// 用来存放函数的数组
var fns = [];

var add = function () {
    for (var i = 0; i < arr.length; i++) {
        (function (i) {
            // 把匿名函数push到fns中
            fns.push(function () {
                // 由于函数引用了上层作用域链的i,当被调用时i值不会被改变
                console.log(arr[i]);
            });
        })(i);
    }
};

// 遍历fns执行数组中的函数
var start = function () {
    for (var i = 0; i < fns.length; i++) {
        // 执行fns中的匿名函数
        fns[i]();
    }
};

add();
start();

// output
// 1
// 2
// 3
点赞
收藏
评论区
推荐文章
待兔 待兔
11个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
菜园前端 菜园前端
2年前
一篇文章教会你什么是闭包
原文链接:什么是闭包?闭包的概念并不复杂,但是它的定义比较绕(就像平时经常用到它,却又说不出来是什么)。可以在一个作用域中调用函数的内部函数并访问到该函数中的作用域的成员,这就是闭包。给一个建议,网上闭包的概念可以搜出来一大堆,但是你真的了解它吗?你有去调
Wesley13 Wesley13
3年前
JS 闭包(内存溢出与内存泄漏)(垃圾回收机制)
1.有关闭包定义闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量闭包的特性:函数内再嵌套函数内部函数可以引用外层的参数和变量参数和变量不会被垃圾回收机制回收
Stella981 Stella981
3年前
Javascript中的方法链式调用
Javascript中的方法链式调用前言为链式调用创建一个对象为什么报错?解决方法使用闭包实现链式调用前言方法的链式调用这个概念,其实是在面向对象编程中比较常见的语法,它能让使用者在一个对象上连续的调用不同的方法。在不使用临时变量存储中间结果的情
Stella981 Stella981
3年前
JS的数组,string类的定义及基本方法
函数:函数在调用的时候,会形成一个私有作用域,内部的变量不会被外面访问,这种保护机制叫闭包。这就意味着函数调用完毕,这个函数形成的栈内存会被销毁。functionfn(){vara12;a;console.log(a)}fn()13fn()13fn()13但有时候我们不希
Stella981 Stella981
3年前
ES6中Generator理解
1\.生成器函数声明  function\ name(args){};2\.yield使用function hello(){    console.log('before hello');  //可看到hello()并不会立刻执行函数, 到第一次next调用时才会    var name 
Stella981 Stella981
3年前
JavaScript函数——闭包
闭包概念只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁例子functionouter(){varlocalVal30;returnlocalVal;}
Wesley13 Wesley13
3年前
JavaWeb 调用接口
JavaWeb 如何调用接口CreateTime2018年4月2日19:04:29Author:Marydon1.所需jar包!(https://oscimg.oschina.net/oscnet/0f139
Stella981 Stella981
3年前
IDA Pro 权威指南学习笔记(十)
栈帧(stackframe)是在程序的运行时栈中分配的内存块,用于特定的函数调用如果一个函数没有执行则不需要内存,当函数被调用时就需要用到内存1.传给函数的参数的值需要存储到函数能够找到它们的位置2.函数在执行过程中可能需要临时的存储空间,通过声明局部变量来分配这类临时空间,这些变量在函数内部使用,函数调用完后,就无法再访问它们
Stella981 Stella981
3年前
JavaScript 使用闭包保护变量 防止污染
使用JavaScript编写插件或团队协作时,可使用闭包来解决此类以下两个问题:1、定义过多全局变量,可能会造成全局变量命名冲突;2、在插件内定义变量,需要保护该变量不被轻易修改;优点:可以把局部变量驻留在内存中,可以避免使用全局变量;在调用过后不会被垃圾机制回收;缺点:避免滥用闭包,占用更多内存的缺点,用完要及时让垃圾回收器回收(fn
Stella981 Stella981
3年前
Golang闭包案例分析与普通函数对比
闭包案例packagemainimport("fmt""strings"//记住一定引入strings包)//①编写一个函数makeSuffix,可以接收一个文件后缀名(比如.jpg),并返回一个闭包//②调用闭包,可以传入一个文件名,如果该文件名没有指