首页 > 其他分享 >闭包

闭包

时间:2022-11-10 20:56:34浏览次数:36  
标签:闭包 function 函数 sum let test

闭包(Closure)

它与 JavaScript 中的垃圾回收(每门语言的垃圾回收是不一样的)有点联系

什么是环境呢?

就比如一个 城市,在城市里面,我们会有很多设施:公园、医院、学校、商业广场...,那么这些设施产生了之后,就构成了这个城市的环境

那么这些环境存在的依据是什么,那是有人生活在这个城市,如果没有人生存在这里了,那么这个城市就会被摧毁掉,要么人为摧毁,要么历经日晒雨淋被摧毁。

反正就是如果没有人住了,这个环境就没有存在的意义了,那么它就应该被摧毁。

同样的,在程序中也是这样的道理,环境存在的依据是被需要

还有要注意的一点,环境里面的设施,诸如公园、医院,它也是有作用范围的,它的作用范围就只有那么大,那么这个作用范围就可以理解为程序中的作用域

我们来看一下这个例子

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
    <style> </style>
</head>
<body>

<script>
    let name = 'jack'
    console.log(name)
</script>
</body>
</html>

这里呢,就有一个全局环境(这里 name 就相当于上面所说的 城市里面的设施公园、学校等)

那么我这里输出了 name 之后,name 这个变量它会不会被删掉呢?

不会,这主要取决于它后续是否会被用到,因为我们这里是一个 HTML 页面,控制台有可能随时访问这些变量,所以不会,除非你把这个页面关了

环境,在计算机当中,就是给我们开辟了一块内存

让我们再来看一个例子

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
    <style></style>
</head>
<body>
    
<script>
    let name = 'jack'
    function sayHello(){
        let word = 'hello world'
        console.log(word)
    }
    sayHello()
</script>
</body>
</html>

在 js 当中,函数也是有自己的环境的

但是这个环境,要注意了,只有在这个函数执行的时候,它才有这个环境,计算机才会给你开辟一个内存空间

默认情况下,外部的环境是无法访问到函数内部环境的变量的,因为函数内部变量的作用域就只是在这个函数里面

所以,当我们把这个函数执行完了,该函数里面的变量就没人能够用到了是吧?所以这个环境,即这片内存,就会被清理掉

因为上文我们说到,当环境不被需要,就会被清理掉

还有一个要注意的地方

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Title</title>
    <style></style>
</head>
<body>

<script>
    let name = 'jack'
	function sayHello(){
        let word = 'hello world'
        console.log(word)
    }
    sayHello()
    sayHello()
    sayHello()
</script>
</body>
</html>

函数每调用一次,就会开辟一次内存空间,每一次都是一个全新的内存空间

上面例子中,函数执行了三次,那么就是开辟了三次内存空间

闭包的使用

实现累加

function test() {
	let n = 1
	function sum() {
		console.log(++n);
	}
	sum()
}
test()
test()
test()

那么这个例子可以累加吗?

不能,因为每一次函数的调用,都是开辟了一个环境,即一片新的内存,并且这片内存执行完,就会被清理

function test() {
    let n = 1
    function sum() {
        console.log(++n);
    }
    return sum
}
let a = test()
a()
a()
a()

我们可以看出,test() 函数的返回值赋值给了变量 a

相当于把 sum 函数一直被 a 用着

在计算机当中,只要这个数据在被使用,那么就不会被清理

相应的,sum 函数所在的环境中所有的变量都不会被清理,注意不是 sum 函数里面的变量,而是 sum 函数所在的环境的变量

我们再来看一个例子

function test() {
    let n = 1
    function sum() {
        console.log(++n);
    }
    return sum
}
let a = test()
a()
a()
a()
let b = test()
b()
b()
b()

这个是因为 函数执行之后 都创建了一块新的内存空间

还有一个例子

function one() {
    let n = 1
    function two() {
        let m = 1
        function three() {
            console.log(++n);
            console.log(++m);
        }
        return three
    }
    return two
}
let a = one()()
a()
a()
a()

可以看出 n 也是保留的

构造函数中使用闭包

function Person() {
    let n = 1
    this.sum = function () {
        console.log(++n);
    }
}
let p = new Person()
p.sum()
p.sum()
p.sum()

只要没有被清理就会形成闭包,这个例子跟下面这个例子是一样的

function Person() {
    let n = 1
    function sum(){
        console.log(++n);
    }
    return {sum}
}
let p = new Person()
p.sum()
p.sum()
p.sum()

引用数据类型 才能形成闭包,基本数据类型 不行

例如

function test() {
    let n = 1
    function add() {
        console.log(++n);
    }
    return {add}
}
let a = test()
a.add()
a.add()
a.add()

可以用闭包封装私有变量

function Person() {
    var age = 0
    this.getAge = function () {
        return age
    }
    this.addAge = function () {
        age++
    }
}
const p1 = new Person()
const p2 = new Person()
p1.getAge()
p2.getAge()

这样外部就无法直接访问变量 age,只能通过闭包访问,我们就近乎实现了面向对象语言中私有变量的效果

总结

闭包的形成必备条件:

标签:闭包,function,函数,sum,let,test
From: https://www.cnblogs.com/zhumenglong/p/16878743.html

相关文章

  • [JavaScript-09]闭包函数
    1.闭包函数//闭包函数vara=123;functionf1(){console.log(a);varb=234;functionf2(){console.log(b);}returnf2;}......
  • JS知识点梳理之作用域、作用域链、柯里化、闭包
    一、作用域与作用域链作用域是指js变量使用时所存在的一个区域,分为全局作用域(window)和局部作用域(function、setTimeout...等都会产生局部作用域)。当局部作用域变量名与......
  • 闭包
    一次看透什么是闭包认识闭包-函数的执行空间不会销毁-外部函数返回一个内部函数-内部函数中使用了外部函数的私有变量闭包函数-概念+函数内的函数-特点:......
  • js 闭包和promise
    闭包概述:闭包就是在函数内部返回一个函数,内部函数可以对外部函数的属性和方法进行引用,外部的属性和方法不会被js垃圾回收机制所回收这个结构就称为闭包函数的生命周......
  • javascript基础知识之闭包和递归
    一,什么是闭包,会出现什么问题?如何避免?1、函数里面包含的子函数,子函数访问父函数的局部变量2、通过return将子函数暴露在全局作用域,子函数就形成闭包3、通过闭包,父函数的局......
  • 闭包小知识:闭包实现数据缓存、变量隔离,以及柯里化的使用场景
    缓存什么是缓存函数?接收一个函数,用闭包将每次函数执行的结果缓存起来缓存例子1: /**闭包实现缓存*属性:有个键--值--->所以可以将缓存数据存放在一个对......
  • 细说JavaScript闭包
    JavaScript闭包难点剖析一、作用域基本介绍ES6之前只有全局作用域与函数作用域两种,ES6出现之后,新增了块级作用域1.全局作用域在JavaScript中,全局变量是挂载在windo......
  • 闭包
    1.概念:在函数内部定义一个子函数,并且return该子函数,然后在子函数中return出外部函数需要访问的变量值;这样外部函数就可以访问内部函数中的变量了2.优点:可以让闭包函数......
  • 闭包
    闭包产生的条件1.需要有一个不销毁的函数2.外部函数里面存在着一个直接或者间接的函数3.在内部函数当中需要引用(使用)到外部函数的局部(私有)的变量闭包的特点:1.......
  • js中的闭包
    什么是闭包呢?严格来说要满足四个条件:1.有函数的嵌套2.内部函数引用外部作用域的变量参数3.返回值是函数4.创建一个对象函数,让其长期驻留1functionfa(){2......