2023/1/15 JS-闭包问题研究

news2025/1/11 22:48:44

1 举个栗子分析执行上下文

1: let a = 3
2: function addTwo(x) {
3:  let ret = x + 2
4:   return ret
5:  }
6: let b = addTwo(a)
7: console.log(b)

为了理解 JavaScript 引擎是如何工作的,让我们详细分析一下:

  1. 在第 1 行,我们在全局执行上下文中声明了一个新变量 a,并将赋值为 3。
  2. 接下来就变得棘手了,第 2 行到第 5 行实际上是在一起的。这里发生了什么?

我们在全局执行上下文中声明了一个名为addTwo的新变量,我们给它分配了什么? -->一个函数定义。

两个括号{}之间的任何内容都被分配给addTwo,函数内部的代码没有被求值,没有被执行,只是存储在一个变量中以备将来使用。

  1. 现在我们在第 6 行。
6: let b = addTwo(a)

首先,我们在全局执行上下文中声明一个新变量,并将其标记为b,变量一经声明,其值即为 undefined。

接下来,仍然在第 6
行,我们看到一个赋值操作符。我们准备给变量b赋一个新值,接下来我们看到一个函数被调用。当看到一个变量后面跟着一个圆括号(…)时,这就是调用函数的信号,接着,函数都返回一些东西(值、对象或
undefined),无论从函数返回什么,都将赋值给变量b。

  1. 但是首先我们需要调用标记为addTwo的函数。JavaScript
    将在其全局执行上下文内存中查找名为addTwo的变量。它是在[步骤 2(或第 2 - 5
    行)中定义]的。

注意:变量[a]作为参数传递给函数。

JavaScript 在全局执行上下文内存中搜索变量a,找到它,发现它的值是 3,并将数字 3 作为参数传递给函数,准备好执行函数。

现在执行上下文将切换【全局执行上下文 -> 函数执行上下文】,创建了一个函数执行上下文,我们将其命名为“addTwo执行上下文”,函数执行上下文被推送到调用栈上。在 addTwo 执行上下文中,我们要做的第一件事是什么?

2: function addTwo(x) {
3:  let ret = x + 2
4:   return ret
5:  }

你可能会说,“在 addTwo 执行上下文中声明了一个新的变量 ret”,这是不对的。

正确的答案是:我们需要先看函数的参数。在 addTwo 执行上下文中声明一个新的变量[x],因为值 3 是作为参数传递的,所以变量 x被赋值为 3。

下一步才是在 addTwo 执行上下文中声明一个新的变量ret。它的值被设置为 undefined(第三行)。

  1. 仍然是第 3 行,需要执行一个相加操作。

首先我们需要x的值,JavaScript 会寻找一个变量x,它会首先在addTwo执行上下文中寻找,找到了一个值为 3。第二个操作数是数字2。两个相加结果为 5 就被分配给变量ret。

  1. 第 4 行,我们返回变量ret的内容,在 addTwo 执行上下文中查找,找到值为 5,返回,函数结束。
  2. 第 4 - 5 行,函数结束。

addTwo 执行上下文被销毁,变量x和ret被消去了,它们已经不存在了。addTwo执行上下文从调用堆栈中弹出,返回值返回给调用【全局】上下文,在这种情况下,调用上下文是全局执行上下文,因为函数addTwo是从全局执行上下文调用的。

  1. 现在我们继续第 4 步的内容,返回值 5 被分配给变量b,此时实际上程序仍然在第 6 行
  2. 在第 7 行,b的值 5 被打印到控制台了。

2 举个栗子分析作用域

我们在函数执行上下文中有变量,在全局执行上下文中有变量。JavaScript 的一个复杂之处在于它如何查找变量,如果在函数执行上下文中找不到变量,它将在调用上下文中寻找它,如果在它的调用上下文中没有找到,就一直往上一级,直到它在全局执行上下文中查找为止。(如果最后找不到,它就是 undefined)。

1: let val1 = 2
2: function multiplyThis(n) {
3:   let ret = n * val1
4:    return ret
5: }
6: let multiplied = multiplyThis(6)
7: console.log('example of scope:', multiplied)
  1. 在全局执行上下文中声明一个新的变量val1,并将其赋值为 2。
  2. 行 2 - 5,声明一个新的变量 multiplyThis,并给它分配一个函数定义。
  3. 第6行,声明一个在全局执行上下文 multiplied 新变量。
  4. 从全局执行上下文内存中查找变量multiplyThis,并将其作为函数执行,传递数字 6 作为参数。

新函数调用(创建函数执行上下文),创建一个新的 multiplyThis 函数执行上下文。

在 multiplyThis 执行上下文中,声明一个变量 n 并将其赋值为 6 -->声明后才会进入函数体内部执行

  1. 执行函数回到第 3 行。

在multiplyThis执行上下文中,声明一个变量ret。

继续第 3 行。对两个操作数 n 和 val1 进行乘法运算。在multiplyThis执行上下文中查找变量 n。 我们在步骤 6中声明了它,它的内容是数字 6。在multiplyThis执行上下文中查找变量val1。 multiplyThis执行上下文没有一个标记为val1 的变量。我们向调用上下文查找,调用上下文是全局执行上下文,在全局执行上下文中寻找 [val1]。它在步骤 1 中定义,数值是 2。

继续第 3 行。将两个操作数相乘并将其赋值给ret变量,6 * 2 = 12,ret 现在值为 12。

  1. 返回ret变量,销毁multiplyThis执行上下文及其变量 ret 和 n 。变量 val1 没有被销毁,因为它是全局执行上下文的一部分。
  2. 回到第 6 行。在调用上下文中,数字 12 赋值给 multiplied 的变量。
  3. 最后在第 7 行,我们在控制台中打印 multiplied 变量的值

3 返回函数的函数[高阶函数]

在第一个例子中,函数addTwo返回一个数字。请记住,函数可以返回任何东西。让我们看一个返回函数的函数示例,因为这对于下方理解闭包非常重要。看栗子:

1: let val = 7
2: function createAdder() {
3:   function addNumbers(a, b) {
4:     let ret = a + b
5:     return ret
6:   }
7:   return addNumbers
8: }
9: let adder = createAdder()
10: let sum = adder(val, 8)
11: console.log('example of function returning a function: ', sum)

高阶函数是什么?

所谓高阶函数,就是一个函数就可以接收另一个函数作为参数,或者是返回一个函数–>常见的高阶函数有map、reduce、filter、sort等

<script>
    var ADD = function add(a) {
        return function (b) {
            return a + b
        }
    }
    console.log(ADD(100)(100)); // 200
</script>

map

<script>
    // map接受一个函数作为参数,不改变原来的数组,只是返回一个全新的数组
    var arr = [1, 2, 3, 4, 5]
    arr.map(item => item * 2)
    console.log(arr);
</script>

在这里插入图片描述

<script>
    // map接受一个函数作为参数,不改变原来的数组,只是返回一个全新的数组
    var arr = [1, 2, 3, 4, 5]
    var arrNew = arr.map(item => item * 2);
    console.log(arrNew);
</script>

在这里插入图片描述

reduce

<script>
    // reduce也是返回一个全新的数组-
    // reduce接受一个函数作为参数:
    // 这个函数要有两个形参,代表数组中的前两项
    // reduce会将这个函数的结果与数组中的第三项再次组成这个函数的两个形参以此类推进行累积操作
    var arr = [1, 2, 3, 4, 5]
    var arr2 = arr.reduce((a, b) => a + b)
    console.log(arr2) // 15
</script>

filter

<script>
    // filter返回过滤后的数组-
    // filter也接收一个函数作为参数:
    // 这个函数将作用于数组中的每个元素,根据该函数每次执行后返回的布尔值来保留结果:
    // 如果是true就保留,如果是false就过滤掉
    var arr = [1, 2, 3, 4, 5]
    var arr3 = arr.filter(item => item % 2 == 0)
    console.log(arr3)// [2,4]
</script>

4 闭包

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起,这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

1 引出闭包概念

错误场景 - 需求: 点击某个按钮, 提示"点击的是第n个按钮"
<body>
<button>测试1</button>
<button>测试2</button>
<button>测试3</button>
<!--
需求: 点击某个按钮, 提示"点击的是第n个按钮"
-->
<script>
    var btns = document.getElementsByTagName('button')
    for (var i = 0, length = btns.length; i < length; i++) {
        var btn = btns[i]
        btn.onclick = function () {  //遍历加监听
            alert('第' + (i + 1) + '个')     //结果 全是[4]
        }
    }
</script>
</body>

此处错误是:直接修改并使用全局变量[i],导致for循环结束后 【对于以上案例 i = 3】,所有点击按钮绑定的弹窗值都是[i+1 = 4 ]
在这里插入图片描述
将变量挂载到自身来解决:

<script>
    var btns = document.getElementsByTagName('button')
    for (var i = 0, length = btns.length; i < length; i++) {
        var btn = btns[i]
        btn.index = i    //存到自身
        btn.onclick = function () {  //遍历加监听
            alert('第' + (this.index + 1) + '个') // 结果正确
        }
    }
</script>

在这里插入图片描述
利用闭包:

<script>
    var btns = document.getElementsByTagName('button')
    // 利用闭包
    for (var i = 0, length = btns.length; i < length; i++) {
        // 此处的j是局部的,它将传入的[i]存入局部的[j]中,这样就能实现效果
        (function (j) {
            var btn = btns[j]
            btn.onclick = function () {
                alert('第' + (j + 1) + '个')
            }
        })(i)
    }
</script>

2 举个闭包栗子分析理解

按照正常逻辑理解:

1: function createCounter() {
2:   let counter = 0
3:   const myFunction = function() {
4:     counter = counter + 1
5:     return counter
6:   }
7:   return myFunction
8: }
9: const increment = createCounter()
10: const c1 = increment()
11: const c2 = increment()
12: const c3 = increment()
13: console.log('example increment', c1, c2, c3)

错误的流程理解,故意按照正常的逻辑流程走,做印证:
在这里插入图片描述
在这里插入图片描述

<script>
    function createCounter() {
        let counter = 0
        const myFunction = function () {
            counter = counter + 1
            return counter
        }
        return myFunction
    }

    const increment = createCounter()
    const c1 = increment()
    const c2 = increment()
    const c3 = increment()
    console.log('example increment', c1, c2, c3)
</script>

在这里插入图片描述
正确的理解:
increment函数记住了那个cunter的值。这是怎么回事?

counter是全局执行上下文的一部分吗?
尝试 console.log(counter),得到undefined的结果,显然不是这样的。
也许,当你调用increment时,它会以某种方式返回它创建的函数(createCounter)?
这怎么可能呢?变量increment包含函数定义,而不是函数的来源,显然也不是这样的。

所以一定有另一种机制。闭包:

它是这样工作的,无论何时声明新函数并将其赋值给变量,都要存储函数定义和闭包。闭包包含在函数创建时作用域中的所有变量,它类似于背包。函数定义附带一个小背包,它的包中存储了函数定义创建时作用域中的所有变化

所以我们上面的解释都是错的,让我们再试一次,但是这次是正确的:

1: function createCounter() {
2:   let counter = 0
3:   const myFunction = function() {
4:     counter = counter + 1
5:     return counter
6:   }
7:   return myFunction
8: }
9: const increment = createCounter()
10: const c1 = increment()
11: const c2 = increment()
12: const c3 = increment()
13: console.log('example increment', c1, c2, c3)

在这里插入图片描述
在这里插入图片描述
** 你此时可能会问,是否有任何函数具有闭包,甚至是在全局范围内创建的函数? **

答案是肯定的。在全局作用域中创建的函数创建闭包,但是由于这些函数是在全局作用域中创建的,所以它们可以访问全局作用域中的所有变量,闭包的概念并不重要。

但当函数返回函数时,闭包的概念就变得更加重要了。返回的函数可以访问不属于全局作用域的变量,但它们仅存在于其闭包中。

5 常见的闭包

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

<script>
    // 1. 将函数作为另一个函数的返回值
    function fn1() {
        var a = 2

        function fn2() {
            a++
            console.log(a)
        }

        return fn2
    }

    var f = fn1()
    f() // 3
    f() // 4
</script>

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

<script>
    // 2. 将函数作为实参传递给另一个函数调用
    function showDelay(msg, time) {
        for (let i = 0; i < 3; i++) {
            setTimeout(function () {
                msg ++
                alert(msg)
            }, time)
        }

    }
    showDelay(1, 2000) // 2 3 4
</script>

6 高阶函数与柯里化

1 从 ES6 高阶箭头函数理解函数柯里化(运用到闭包)

<script>
    function add(a) {
        return function (b) {
            return a + b
        }
    }

    var add3 = add(3) // add3表示一个指向函数的变量 可以当成函数调用名来用
    console.log(add3(4) === 3 + 4); // true
</script>

再简化一下,可以写成如下形式:

<script>
    let add = function (a) {
        var param = a;
        var innerFun = function (b) {
            return param + b;
        }
        return innerFun;
    }
</script>

虽然好像没什么意义,但是很显然上述使用了[闭包],而且该函数的返回值是一个函数。其实,这就是高阶函数的定义:以函数为参数或者返回值是函数的函数。

<script>
    let add = function (a) { // a = 100 100 100
        var param = a; // param = 100 
        console.log(' var param = a;')
        var innerFun = function (b) { // b = 200 200 200
            param = param + param // 200 400 800
            return param + b; // 400 600 1000
        }
        return innerFun;
    }
    var ADD = add(100)
    console.log(ADD(200)); // 400
    console.log(ADD(200)); // 600
    console.log(ADD(200)); // 1000
</script>

在这里插入图片描述

2 柯里化

关键就是理解柯里化,其实可以把它理解成,柯里化后,将第一个参数变量存在函数里面了(闭包),然后本来需要n个参数的函数可以变成只需要剩下的(n - 1个)参数就可以调用,比如:

let add = x => y => x + y
let add2 = add(2)
-*----------------------------------
本来完成 add 这个操作,应该是这样调用
let add = (x, y) => x + y
add(2,3)
----------------------------------
1. 而现在 add2 函数完成同样操作只需要一个参数,这在函数式编程中广泛应用。
let add = x => y => x + y
let add2 = add(2)
2.详细解释一下,就是 add2 函数 等价于 有了 x 这个闭包变量的 y => x + y 函数,并且此时 x = 2,所以此时调用
add2(3) === 2 + 3

3 总结

如果是a => b => c => {xxx}这种多次柯里化的,如何理解?

理解:前n - 1次调用,其实是提前将参数传递进去,并没有调用最内层函数体,最后一次调用才会调用最内层函数体,并返回最内层函数体的返回值

结合上文可知,这里的多个连续箭头(无论俩个箭头函数三个及以上)函数连在一起 就是在柯里化。所以连续箭头函数就是多次柯里化函数的 es6 写法。

调用特点:let test = a => b => c => {xxx}

比如对于上面的 test 函数,它有 3 个箭头, 这个函数要被调用 3test(a)(b)(c),前两次调用只是在传递参数,只有最后依次调用才会返回 {xxx} 代码段的返回值,并且在 {xxx} 代码段中可以调用 a,b,c

7 闭包的作用

  • 使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期)
  • 让函数外部可以操作(读写)到函数内部的数据(变量/函数)
    问题:
    函数执行完后, 函数内部声明的局部变量是否还存在?
一般是不存在, 存在于闭中的变量才可能存在

在函数外部能直接访问函数内部的局部变量吗?

不能, 但我们可以通过闭包让外部操作它

8 闭包的生命周期

产生: 在嵌套内部函数定义执行完时就产生了(不是在调用)
死亡: 在嵌套的内部函数成为垃圾对象时,即没有人指向它时死亡,通常置为[null],当然指向其他也行,但不安全(容易污染变量)

<script>
    //闭包的生命周期
    function fn1() {
        //此时闭包就已经产生了(函数提升,实际上[fn2]提升到了第一行, 内部函数对象已经创建了)
        var a = 2

        function fn2() { //如果时[let fn2=function(){}],那么在这行才会产生闭包
            a++
            console.log(a)
        }

        return fn2
    }

    var f = fn1()
    f() // 3
    f() // 4
    f = null //闭包死亡(包含闭包的函数对象成为垃圾对象)
</script>

9闭包的应用

闭包的应用 : 定义JS模块

  1. 具有特定功能的js文件
  2. 将所有的数据和功能都封装在一个函数内部(私有的)
  3. 只向外暴露一个包信n个方法的对象或函数
  4. 模块的使用者, 只需要通过模块暴露的对象调用方法来实现对应的功能
模块定义

在这里插入图片描述

模块的调用

在这里插入图片描述
在这里插入图片描述

10 闭包的缺点及解决

缺点:

  • 函数执行完后, 函数内的局部变量没有释放, 占用内存时间会变长
  • 容易造成内存泄露
    解决:
  • 能不用闭包就不用
  • 及时释放
function fn1() {
    var arr = new Array(100000)

    function fn2() {
        console.log(arr.length)
    }

    return fn2
}

var f = fn1()
f()
f = null //让内部函数成为垃圾对象-->回收闭包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/165720.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux chattr命令

Linux chattr命令Linux 命令大全Linux chattr命令用于改变文件属性。这项指令可改变存放在ext2文件系统上的文件或目录属性&#xff0c;这些属性共有以下8种模式&#xff1a;a&#xff1a;让文件或目录仅供附加用途。b&#xff1a;不更新文件或目录的最后存取时间。c&#xff1…

从上到下看内存

从上到下看内存 1. 本篇目录 内存条,总线,DMAC 内存管理内存分类 内存相关的系统调用 java中的内存 2. 内存条,总线,DMAC 内存条 内存条&#xff1a;内存条其实是非常常见的一个组件。内存条是插在主板上的。 总线 内存条插好以后&#xff0c;计算机之间要进行交互。…

Linux 中断子系统(四):GIC中断初始化

以我手中的 imx6ull开发板为例。 如果使用设备树的话就需要在设备树中设置好中断属性信息,Linux 内核通过读取设备树中的中断属性信息来配置中断。对于中断控制器而言,设备树绑定信息参考文档 Documentation/devicetree/bindings/arm/gic.txt。 打开 imx6ull.dtsi 文件,其…

UDS诊断系列介绍12-11服务

本文框架1. 系列介绍1.1 11服务概述2. 11服务请求与应答2.1 11服务请求2.2 11服务正响应2.3 11服务否定响应3. Autosar系列文章快速链接1. 系列介绍 UDS&#xff08;Unified Diagnostic Services&#xff09;协议&#xff0c;即统一的诊断服务&#xff0c;是面向整车所有ECU的…

三种方法解决React类组件中this指向问题

从onClick事件不加括号说起 import React from react import ./App.css class TestComponent extends React.Component {clickHandler () {console.log(111)console.log(this指向&#xff1a;, this)}render () {return (<button onClick{this.clickHandler()}>点击我&l…

机器学习实战4:基于马尔科夫随机场的图像分割(附Python代码)

目录0 写在前面1 图像分割问题2 图像像素邻域3 观测场与标记场4 马尔科夫随机场建模5 Python实现5.1 计算能量函数5.2 退火优化5.3 效果展示0 写在前面 机器学习强基计划聚焦深度和广度&#xff0c;加深对机器学习模型的理解与应用。“深”在详细推导算法模型背后的数学原理&a…

分享6个对象数组去重的方法

大家好&#xff0c;关于对象数组去重的业务场景&#xff0c;想必大家都遇到过类似的需求吧&#xff0c;针对这样的需求&#xff0c;你是怎么做的呢。下面我就先和大家讨论下基于对象的某个属性如何去重。方法一&#xff1a;使用 .filter() 和 .findIndex() 相结合的方法使用 fi…

基于AD Event日志监测AdminSDHolder

01、简介 AdminSDHolder是一个特殊的AD容器&#xff0c;通常作为某些特权组成员的对象的安全模板。Active Directory将采用AdminSDHolder对象的ACL并定期将其应用于所有受保护的AD账户和组&#xff0c;以防止意外和无意的修改并确保对这些对象的访问是安全的。如果攻击者能完全…

## Leetcode刷题Day24-------------------回溯算法

Leetcode刷题Day24-------------------回溯算法 1. 理论基础 题目链接/文章讲解&#xff1a;https://programmercarl.com/%E5%9B%9E%E6%BA%AF%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html视频讲解&#xff1a;https://www.bilibili.com/video/BV1cy4y167mM …

Linux文件目录与路径、内容查找命令及文件颜色知识总结

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java案例分…

SpringBoot 整合Shiro实现动态权限加载更新+Session共享+单点登录

一.说明 Shiro是一个安全框架,项目中主要用它做认证,授权,加密,以及用户的会话管理,虽然Shiro没有SpringSecurity功能更丰富,但是它轻量,简单,在项目中通常业务需求Shiro也都能胜任. 二.项目环境 MyBatis-Plus版本: 3.1.0 SpringBoot版本:2.1.5 JDK版本:1.8 Shiro版本:1.4…

ASUS X415安装系统找不到硬盘解决办法

同事让我帮忙安装系统&#xff0c;笔记本电脑型号是ASUS X415。原本以为是手到擒来的事情&#xff0c;结果我在上面还是消耗了不少时间。 现象 老毛桃PE 无法识别到硬盘。微PE可以识别到硬盘&#xff0c;但是系统安装以后&#xff0c;无法正常启动。启动出现蓝屏。或者无限等…

codewars闯关玩耍1

codewars闯关玩耍1 codewars网址&#xff1a;https://www.codewars.com/dashboard 大一时在知乎上看到的网站&#xff0c;然后 点击、收藏、吃灰 一键三连&#xff0c;最近翻收藏夹的时候突然又看见了决定进来玩玩&#xff0c;练练英语&#xff0c;巩固下python 以后此系列&a…

javaweb10 JSP语法、JSTL、EL表达式、JSP标签、九大内置对象

文章目录一、JSP简介二、JSP原理三、JSP语法四、JSP指令五、九大内置对象六、EL表达式七、JSP标签八、JSTL标签一、JSP简介 JSP&#xff08;java sever pages&#xff09;&#xff1a;java服务器端页面&#xff0c;和servlet一样&#xff0c;用于动态web技术 写JSP就像在写HTM…

中国to B应用软件的突破之路

我曾经随手画过一个很简单的图&#xff1a;我就分为供需两端。&#xff08;1&#xff09;如何让生意越做越大&#xff1f;那就在需侧&#xff0c;增加尽量多的交互。有人理解在营销环节-客户关系触点经营&#xff0c;有人理解在销售环节-多渠道多业态销售&#xff08;如电话销售…

振弦采集模块配置工具VMTool生成寄存器值

振弦采集模块配置工具VMTool生成寄存器值 生成寄存器值 VMXXX 有很多按位使用的寄存器&#xff0c; 使用 VMTool 工具可进行方便的设置&#xff0c;当需要知道寄存器的实际值时&#xff0c;可通过以下两种方法获取。 &#xff08;保持【 自动读取】 复选框为非选中状态&#xf…

Unity 简易音乐播放系统

前言 众所周知, Unity自带音效播放没有回调,不能自动播放clip列表; 所以简单实现一个带自动播放功能的接口,用以实现音乐列表的逐个播放. 一. 功能分析 首先要求切换场景时音乐不停,只在需要时播放其次即传入音乐名和播放次数,即可将该音乐循环播放指定次数可以直接传入一个…

【OpenCV 例程 300篇】256. 特征检测之 CenSurE(StarDetector)算法

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】256. 特征检测之 CenSurE&#xff08;StarDetector&#xff09;算法 6.9.1 算法简介 中心环绕算法&#xff08;Center Surround Extremas, CenSurE&#xff09;是 Agrawal M 等于 2008年提出的关键…

K8S StatefulSet基本使用

K8S StatefulSet 清空K8S对象 为了避免之前学习的内容造成的影响&#xff0c;先手动把K8S集群中的所有对象清空&#xff0c;使用一个全新的环境来学习StatefulSet的基本使用。 查看对象 查看service对象 kubectl get services查看ReplicaSet对象 kubectl get rs查看Repli…