首页 > 其他分享 >闭包

闭包

时间:2023-04-25 15:38:00浏览次数:28  
标签:闭包 function 函数 -- object var

闭包理解

如何产生闭包

  • 当一个嵌套的内部(子)函数引用了嵌套外部(父)函数的变量(函数)时--就产生了闭包

闭包是什么

  • 使用chrome调试查看

  • 理解一 -- 闭包是嵌套的内部函数

  • 理解二 -- 闭包是包含被引用变量(函数)的对象

  • 闭包存在于嵌套的内部函数中

  • 产生闭包的条件

  • 函数嵌套

  • 内部函数引用了外部函数的数据(变量或函数)

<script>
    function fn1() {
        var a = 3;
        function fn2() {
            console.log(a);
        }
        fn2();
    }
    fn1();
</script>

常见闭包

将函数作为另一个函数的返回值

function fn1() {
    var a = 2;
    function fn2() {
        a++;
        console.log(a);
    }
    return fn2;
}
var f = fn1();
f();    //3--fn1的返回值是fn2--相当于调用了fn2()--相当于fn1()()
f();    //4--闭包不会消失--第一次fn1()执行时--闭包内的数据是3--第二次执行时就是4

将函数作为实参传递给另一个函数调用

function showDelay(msg, time) {
    setTimeout(function () {
        console.log(msg);   //闭包
    }, time);
}
showDelay('zao', 2000);

闭包的作用

  • 使用函数内部的变量在函数执行完后--仍然存活在内存中--延长了局部变量的生命周期

  • 让函数外部可以操作(读写)到函数内部的数据--变量/函数

问题

  • 函数执行完--函数内部声明的局部变量是否还存在--一般不存在,存在于闭包中的变量才可能存在
  • 在函数外部能直接访问函数内部的局部变量吗--不能,但可以通过闭包让外部操作它

闭包的生命周期

  • 产生--在嵌套内部函数定义执行完时就产生了
  • 死亡--在嵌套内部函数成为垃圾对象时
function fn1(){
    // 闭包产生--函数提升--内部函数已经创建了
    var a = 2;
    function fn2(){
        a++;
        console.log(a);
    }
    return fn2;
}
//只要有变量引用fn1()闭包就一直存在
var f = fn1();
f();
f();
//闭包死亡--包含闭包的函数成为垃圾对象
f = null;

闭包的应用

定义JS模块

  • 具有特定功能的js文件
  • 将所有数据和功能都封装在一个函数内部--私有
  • 只向外暴露一个包含n个方法的对象或函数
  • 模块的使用者--只需通过模块暴露的对象调用方法来实现对应的功能
//JS文件
function myMoudle() {
    var msg = 'zaoya';
    function doSomething() {
        //toUpperCase--字符串转换为大写
        console.log('doSomething()' + msg.toUpperCase());
    }
    function doOtherthing() {
        //toLowerCase--字符串转换为小写
        console.log('doOtherthing()' + msg.toLowerCase());
    }
    //向外暴露对象
    return {
        doSomething: doSomething,
        doOtherthing: doOtherthing
    }
}

//html文件
<script src="myMoudle.js"></script>
<script>
    let fn = myMoudle();
	fn.doSomething();
	fn.doOtherthing();
</script>
//JS文件
(function myMoudle1() {
    let msg = 'zaozao';
    function doSomething() {
        console.log('doSomething()' + msg.toUpperCase);
    };
    function doOtherthing() {
        console.log('doOtherthing()' + msg.toLowerCase);
    }
    window.myMoudle1 = {
        doSomething: doSomething,
        doOtherthing: doOtherthing
    }
})()

//html文件
<script src="myMoudle1.js"></script>
<script>
	myMoudle1.doSomething();
	myMoudle1.doOtherthing();
</script>

闭包的缺点

缺点

  • 函数执行完后--函数内的局部变量没有释放--占用内存时间会变长
  • 容易造成内存泄漏

解决

  • 能不用闭包就不用闭包
  • 及时释放

内存溢出

  • 一种程序运行出现的错误
  • 当程序运行需要的内存超过了剩余的内存时--就会抛出内存溢出的错误

内存泄漏

  • 占用的内存没有及时释放
  • 内存泄漏积累多了就容易导致内存溢出

常见内存泄漏

  • 意外的全局变量
  • 没有及时清理的计时器或回调函数
  • 闭包

面试题

var name = 'The Window';
var object = {
    name: 'My Object',
    getNameFunc: function () {
        return function () {
            return this.name;
        }
    }
}
//object.getNameFunc()--是对象调用--通过object调用--this为object
//通过object.getNameFunc()--调用函数--object.getNameFunc()()--是函数调用--this为window
alert(object.getNameFunc()());  //The Window
var name2 = 'The Window';
var object = {
    name2: 'My Object',
           var that = this;
        return function () {
            return that.name2;
        }
    }
}
//object.getNameFunc()--是对象调用--通过object调用--this为object
//object.getNameFunc()()--中that是object.getNameFunc()的this--指向object
alert(object.getNameFunc()())       //My Object

标签:闭包,function,函数,--,object,var
From: https://www.cnblogs.com/Liu-h/p/17352722.html

相关文章

  • java程序new对象后加大括号{},匿名类,闭包,lamda表达式相关
     这种在源码中经常出现,所以我拿出来说一说步骤1 new一个匿名子类对象    我姑且叫这种情况为“匿名子类”吧,就是有这样的情况,你new一个类的时候直接加一对花括号,实际上已经创建了它的一个匿名子类。老实说,我第一次见到这种写法也是懵逼的。比如我有一个父类publicc......
  • Rust语言 学习12 闭包和迭代器
    一、闭包入门usestd::thread;usestd::time::Duration;fnmain(){letspecified_value=10;letrandom_number=7;generate_workout(specified_value,random_number);}fngenerate_workout(intensity:u32,random_number:u32){//定义一个函数闭包......
  • Python常见面试题016. 请实现如下功能|谈谈你对闭包的理解
    016.请实现如下功能|谈谈你对闭包的理解摘自<流畅的python>第七章函数装饰器和闭包实现一个函数(可以不是函数)avg,计算不断增加的系列值的平均值,效果如下defavg(...):passavg(10)=>返回10avg(20)=>返回10+20的平均值15avg(30)=>返回10+20+30的平均值20......
  • Go 语言函数闭包
    Go语言支持匿名函数,可作为闭包。匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。以下实例中,我们创建了函数getSequence(),返回另外一个函数。该函数的目的是在闭包中递增i变量,代码如下:实例package mainimport "fmt"func ge......
  • Go语言闭包
    说到Go语言的闭包,不得不说说全局变量和局部变量全局变量的特点:1.常驻内存2.污染全局局部变量的特点:1.不常驻内存2.不污染全局而Go语言的闭包可以做到1.可以让变量常驻内存2.可以让变量不污染全局所以闭包主要是为了避免全局变量的滥用。闭......
  • 离散数学关系的基本运算和关系的性质闭包
    文章目录关系的运算基本运算关系的复合运算关系的逆运算关系的性质一.自反性和反自反性二.对称性和反对称性三.传递性关系性质的判定定理关系的性质闭包关系的幂运算传递闭包的关系矩阵闭包关系的性质多重闭包关系的运算定义5.2.1:设R,S是X到Y的二元关系,则R∪S,R∩S,R-S,~R,R⨁S也......
  • Rust编程语言入门之函数式语言特性:-迭代器和闭包
    函数式语言特性:-迭代器和闭包本章内容闭包(closures)迭代器(iterators)优化改善12章的实例项目讨论闭包和迭代器的运行时性能一、闭包(1)-使用闭包创建抽象行为什么是闭包(closure)闭包:可以捕获其所在环境的匿名函数。闭包:是匿名函数保存为变量、作为参数可在一个地方......
  • python基础七(函数名称空间及作用域、函数对象、函数嵌套、闭包函数、装饰器)
    一名称空间(namespaces):存放名字的地方,是对栈区的划分。 有了名称空间之后,就可以在栈区中存放相同的名字,详细的名称空间。分三种1.1内建名称空间存放的名字:存放的python解释器内置的名字print<built-infunctionprint>存活周期:python解释器启动则产生,python解释器关闭则销毁......
  • swift tabview 带参数请求网络。多条目展示。json解析,逃逸闭包
    效果:用到的第三方#Uncommentthenextlinetodefineaglobalplatformforyourprojectplatform:ios,'9.0'target'News'do#Commentthenextlineifyoudon'twanttousedynamicframeworksuse_frameworks!#PodsforNewsp......
  • php关于闭包(匿名函数)的理解
    匿名函数(Anonymousfunctions),也叫闭包函数(closures),允许临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。匿名函数目前是通过 Closure 类来实现的。Example#1匿名函数示例<?phpechopreg_replace_callback('~-([a-z])~',func......