当前位置: 首页 > news >正文

前端(十三)——JavaScript 闭包的奥秘与高级用法探索

在这里插入图片描述

😶博主:小猫娃来啦
😶文章核心:深入理解 JavaScript 中的闭包

文章目录

  • 不理解闭包?这玩意很难?
  • 闭包的定义与原理
    • 闭包是什么
    • 创建一个闭包
  • 闭包的应用场景
  • 闭包与作用域
    • 闭包与作用域之间的关系
    • 全局作用域、函数作用域和闭包的区别
    • 闭包对变量生命周期的影响
  • 闭包的优点和挑战
    • 闭包带来的优点
    • 闭包可能带来的挑战
    • 使用闭包的注意事项
  • 闭包使用案例和实际场景
  • 学习资源推荐

不理解闭包?这玩意很难?

⭐⭐⭐关键点1

想象一下你在家里做饭,准备了一些食材和炉灶。闭包就像是你在炉灶旁边放了一个小盒子,里面有你需要用到的调料和工具。

这个小盒子就是一个闭包,里面装着你做饭时所需的东西。当你开火炒菜时,你可以随意使用盒子里的调料和工具,而不需要每次去厨房找。

闭包的作用就是让你方便地使用盒子里的东西,而不需要每次都去找它们。它把函数和相关的数据打包在一起,形成一个容器,你可以随时拿来使用。

这样的话,闭包就是帮助你更方便地存储和访问函数需要的数据,就像是一个移动的小工具箱,可以随时拿来用,而不需要每次都重新准备。

闭包的两个特点:
⭐⭐⭐关键点2

  1. 闭包内的函数可以访问外部函数中定义的变量。就像是一个保险柜,只有它自己知道密码,可以打开柜门取出里面的东西。
  2. 闭包函数可以保存在其他地方并被调用,但它仍然可以访问它创建时的环境。就像是一个存钱罐,你可以把它放在任何地方,以后需要时还可以取出里面的钱。

闭包有什么用呢?

  • 封装:闭包可以帮助我们创建私有变量和函数,避免命名冲突,保护数据安全。
  • 数据保持:闭包可以让函数内部的变量在函数执行结束后依然存在,方便后续使用。
  • 回调和异步操作:闭包常用于创建回调函数,处理异步操作时能够保存一些状态信息并进行访问和更新。
  • 模块化开发:闭包可以帮助我们创建模块化的代码,把相关功能和数据封装在闭包中,提供更高层次的抽象和封装。

如果你是对闭包有深入理解的。你肯定知道,在使用时要慎重,不能滥用闭包,否则可能会导致内存泄漏和性能消耗问题。

那么为什么会导致内存泄漏并且消耗性能呢?

⭐⭐⭐关键点3

假设你经常旅行,每次都会随身带着一个行李箱。如果你一直把不用的物品留在行李箱里,时间久了,行李箱就会变得很重,而且占用了不必要的空间。

闭包也是一样的道理。如果你滥用闭包,将不再需要的变量存储在闭包中,并且没有及时释放它们,就会导致内存泄漏和性能问题。

内存泄漏就好像行李箱里的物品积压太多,无法清理干净,最终导致浪费资源。如果我们不断创建和使用闭包,但又没有及时释放不再需要的部分,那么这些变量将一直占据着内存,造成内存的浪费。

性能问题则类似于携带过重的行李箱,给你的旅程增加了负担。如果闭包中存储了大量的变量和函数,每次使用它们时都要在内存中查找,这将耗费更多的时间和计算资源。对于大型项目或频繁调用的代码,这可能会显著影响程序的性能。

因此,在使用闭包时,我们需要慎重对待。及时释放不再需要的资源,避免滥用闭包,以免引起内存泄漏和性能问题。就像旅行时要定期整理行李箱一样,我们也要确保及时清理不再需要的闭包,让代码更加高效和可靠。

如果你不理解闭包,那么现在你应该对闭包有些认识了。总而言之,闭包是个超级大盒子。你如果是理发师,那这个大盒子里就装着各种发蜡,剪刀,洗发水,刮胡刀,剃头刀,染发剂,烫头的药水,吹风机等等。你要用什么就拿什么,这样子就会看起来非常规整,不需要满房间去找我需要的工具。但也有坏处,虽然看起来这个事归规规矩。但是如果东西太多,把某些物品压在箱底了,你想用的话,得从最上面的物品一直往下翻,会很累。如何避免呢?那就是尽可能的少放东西,一个工具用完放在固定位置,不要乱扔,避免下次用的时候难找。

所谓闭包,就是这么一个东西。

好的闭包:
在这里插入图片描述糟糕的闭包:
在这里插入图片描述

假如你是程序,你说第一张图和第二张图,哪个图里找东西费事?你喜欢哪个闭包?

所以,闭包不仅是一种技术,更是一种思维方式,它可以帮助我们编写更优雅和高效的代码,也可以让我们的生活各个方面井井有条。


闭包的定义与原理

闭包是什么

闭包是一种特殊的函数对象,它包含了函数的代码和在创建该函数时所处环境中的变量。简单来说,闭包就是一个函数和与之相关的引用的组合体。

当一个函数内部定义了另一个函数,并且内部函数可以访问外部函数的变量时,我们就可以称这个内部函数为闭包。闭包可以“记住”创建它时的环境,即使在其定义的上下文已经不存在时仍然可以访问那些变量。

这就像是一个函数带着一个包裹,包裹里面装着函数所需的数据。当我们调用这个闭包时,它会携带着这个包裹,使得内部函数能够继续访问和操作包裹里的数据。

闭包有几个重要的特点:

  • 可以捕获并访问定义它的外部函数的变量。
  • 可以在函数外部被调用,以便在不同的上下文中使用。
  • 可以被当作参数传递给其他函数,或者作为函数的返回值。

总结起来,闭包就是一个函数和它周围的状态(即定义它时所处的环境)的组合。它能够记住创建时的上下文,并允许我们在以后的任何时间访问和操作这些数据。

创建一个闭包

var a = 5;var outerFunction = function() {var b = 3;function innerFunction() {return a + b;}return innerFunction;
};var result = outerFunction();
console.log(result()); // 输出:8

我们分析一下这段代码:
首先,在全局作用域中定义了变量 a,赋值为 5
然后,定义一个匿名函数,并将其赋值给 outerFunction 变量。在匿名函数内部,定义了变量 b,赋值为 3。然后在匿名函数内部定义了 innerFunction 函数,它引用了外部函数的变量 a 和内部函数的变量 b。最后,返回内部函数 innerFunction,形成了闭包。
紧接着,调用外部函数 outerFunction 并将返回的结果赋值给 result 变量。这里实际上是获取了一个闭包,该闭包包含了 innerFunction 和它引用的外部变量 ab
最后,调用闭包中的 innerFunction 函数,它会返回 a + b 的值。在这里,a 的值是外部变量的值 5,而 b 的值是外部函数中的变量 3。因此,result() 的结果为 8

通过在函数内部定义另一个函数并引用外部函数的变量,这就成功地创建了一个闭包。闭包可以访问和操作外部函数的变量,即使外部函数已经执行完毕。这样我们可以在之后的任何时间调用闭包,并且它会使用当初创建时的上下文信息。


基于上面的例子,我们分析一下闭包的原理和工作机制

闭包是一种特殊的函数对象,它包含了函数本身以及它被创建时所处的环境(外部函数的变量)。这使得闭包可以在函数执行完毕后仍然访问和操作其外部函数的变量。

闭包的工作机制可以总结为以下几个步骤:

  • 函数定义:当一个函数内部定义了另一个函数时,内部函数就可以引用外部函数的变量。

  • 变量捕获:当内部函数引用外部函数的变量时,JavaScript 引擎会在内部函数的执行环境中创建一个变量的引用。这个引用捕获了外部函数的变量,并保存在闭包中。

  • 外部函数执行结束:在外部函数执行完成后,根据 JavaScript 的垃圾回收机制,其局部变量通常会被销毁。但是,由于内部函数仍然引用了这些变量,它们不会被回收,而是被包含在闭包中。

  • 闭包形成:当外部函数返回内部函数时,实际上返回的是该内部函数以及它所引用的外部变量的闭包。闭包包含了函数本身以及它被创建时的环境信息。

  • 闭包的使用:返回的闭包可以在之后的任何时间内被调用,它能够访问和操作外部函数的变量,即使外部函数已经执行完毕。这是因为闭包中保存了被捕获的变量的引用。

闭包的原理基于 JavaScript 的词法作用域规则和垃圾回收机制。通过利用闭包,我们可以实现一些高级的编程技巧,例如模块模式、私有变量和函数的记忆化等。同时也需要注意,由于闭包可以保留对外部变量的引用,所以在使用闭包时要小心内存管理,避免造成内存泄漏。


闭包的应用场景

模块化开发: 闭包在模块化开发中起到了封装和隐藏变量的作用,使得我们可以创建独立的模块,并且只暴露需要外部访问的接口。这种方式可以提高代码可维护性和重用性。

var counter = (function() {var count = 0;return {increment: function() {count++;},decrement: function() {count--;},getCount: function() {return count;}};
})();counter.increment();
console.log(counter.getCount()); // 输出: 1

在上面的例子中,我们使用闭包创建了一个计数器模块。count 是一个私有变量,只有通过返回的对象才能访问它。这样可以防止外部直接修改计数值,同时提供了三个方法 incrementdecrementgetCount 来操作计数器。


事件处理: 闭包经常用于事件处理函数,它可以捕获事件发生时的上下文信息,并在之后的某个时间点执行这个函数。这使得事件处理函数可以访问当前作用域以及外部作用域中的变量。

function createButton() {var count = 0;var button = document.createElement('button');button.innerText = 'Click me';button.addEventListener('click', function() {count++;console.log('Button clicked ' + count + ' times');});return button;
}var myButton = createButton();
document.body.appendChild(myButton);

我们创建了一个按钮,并给它添加了点击事件处理函数。事件处理函数可以访问并更新外部函数 createButton 中的变量 count,每次点击按钮时计数器就会增加。


异步编程: 闭包在异步编程中也有广泛的应用。由于 JavaScript 是单线程的,异步操作常常涉及到回调函数。而闭包可以捕获回调函数所需的上下文信息,使得在回调函数被调用时能够访问正确的变量。

function fetchData(url, callback) {// 发起异步请求fetch(url).then(function(response) {// 根据响应处理数据return response.json();}).then(function(data) {// 调用回调函数并传入数据callback(data);});
}function displayData(data) {console.log(data);
}fetchData('接口链接', displayData); // 异步获取数据并在回调函数中显示

这个例子中,fetchData 函数使用闭包实现了异步数据的获取。在最后一步调用 fetchData 时,我们传入一个回调函数 displayData,当数据请求成功后会被调用并传入获取到的数据。


闭包与作用域

闭包与作用域之间的关系

闭包与作用域之间有着密切的关系。在理解闭包的概念时,有必要先理解作用域的概念。

作用域定义了变量和函数的可访问范围。在JavaScript中,作用域通常是通过函数来创建的。每当你声明一个函数时,都会创建一个新的作用域。

闭包是指函数能够访问其词法作用域以外的变量的能力。具体来说,当一个函数内部引用了外部作用域的变量时,即使外部函数已经执行完毕,这个函数仍然可以使用该变量。

闭包实际上是一个函数和其相关的词法环境的组合。词法环境包含了在函数定义时所存在的所有局部变量、参数和其它函数。

闭包的出现是由于JavaScript采用的是词法作用域,它在函数定义的时候就决定了变量的作用域。而不同的函数可以访问不同的作用域,从而形成了闭包。
下面的例子可以更好地说明闭包与作用域之间的关系:

function outer() {var x = 10;function inner() {console.log(x); // 内部函数引用了外部函数的变量x}return inner;
}var closure = outer(); // 外部函数执行,并将内部函数返回
closure(); // 输出: 10

在这个例子中,inner 函数引用了外部函数 outer 中的变量 x。即使 outer 函数执行完毕并返回了 inner 函数,inner 函数依然可以访问和使用 x 变量。这是因为 inner 函数形成了一个闭包,包含了对 outer 函数作用域的引用。
可以总结如下:

  • 作用域决定了哪些变量可以被访问和使用。
  • 闭包可以让函数继续访问外部作用域中的变量,即使外部函数已经执行完毕。
  • 闭包是由函数和其相关的词法环境组成,它允许函数访问外部作用域中的变量。

理解闭包与作用域之间的关系对于在JavaScript中正确使用闭包非常重要。它可以帮助我们更好地封装变量、实现模块化开发并处理异步操作等。


全局作用域、函数作用域和闭包的区别

全局作用域、函数作用域和闭包是 JavaScript 中不同的概念,它们在作用域范围和变量访问方面有所不同。

  1. 全局作用域:
  • 全局作用域是在整个代码中都可访问的作用域。
  • 在浏览器中,全局作用域一般是指在 <script> 标签或外部 JavaScript 文件中定义的变量和函数。
  • 全局作用域中声明的变量可以被后续的代码任意访问和修改。
  1. 函数作用域:
  • 函数作用域是指在函数内部声明的变量只能在函数内部使用,外部无法访问。
  • 函数作用域中的变量称为局部变量,它们只在函数内部有效。
  • 每当函数被调用时,都会创建一个新的函数作用域,函数执行完毕后,其内部的变量会被销毁。
  1. 闭包:
  • 闭包是指函数能够访问其定义时所在的词法作用域,即使函数在当前作用域外被调用。
  • 闭包通过将函数及其相关的引用变量一起封装,形成一个独立的包裹,使得函数能够继续访问外部作用域中的变量。
  • 闭包常用来实现函数的状态保留和数据私有化,以及模块化编程等功能。
  • 闭包可以延长变量的生命周期,使得函数在不同的上下文中共享数据。

区别:

  • 全局作用域是在整个代码中都可访问的作用域,函数作用域仅在函数内部有效,而闭包是函数能够访问其定义时所在的词法作用域。
  • 全局作用域中的变量可以被后续的代码任意访问和修改,而函数作用域中的变量只在函数内部有效,外部无法访问。闭包可以让函数继续访问外部作用域中的变量,即使外部函数已经执行完毕。
  • 全局作用域具有全局性,容易引起变量冲突和全局污染的问题;函数作用域和闭包提供了更好的封装性和隔离性,可以减少命名冲突和对全局命名空间的依赖。

总结: 全局作用域是最外层的作用域,在整个代码中都可访问;函数作用域是函数内部的作用域,只在函数内部有效;闭包是函数能够访问其定义时所在的词法作用域,即使函数在当前作用域外被调用。它们在作用域范围和变量访问方面有所不同,适用于不同的编程场景和需求。


闭包对变量生命周期的影响

闭包对变量生命周期的影响是延长了变量的生命周期。在普通的函数中,函数执行完毕后,函数作用域内的变量会被销毁,无法再被访问。但是当函数形成闭包时,闭包会持有函数内部的变量及其引用,使得这些变量在函数执行完毕后仍然可以被访问和操作。

具体来说,闭包通过保留其所在词法作用域的引用,使得这个作用域中的变量不会被垃圾回收机制回收,从而延长了变量的生命周期。这意味着在闭包外部的代码仍然可以访问和修改闭包中引用的变量。

闭包对变量生命周期的影响可以有以下几个方面:

  1. 变量在函数执行完毕后仍然可访问:闭包使得函数内部的变量不会随着函数的执行完毕而被销毁,从而使得外部代码仍然可以访问和操作这些变量。这为实现某些功能(如状态保留、数据私有化等)提供了可能性。
  2. 变量的值在闭包中得到保留:闭包中引用的变量的值会被保留下来,即使该变量原本位于函数作用域中。这可以让函数在不同的上下文中共享数据,实现了一种记忆效应。
  3. 变量可能无法被垃圾回收:由于闭包持有对变量的引用,导致这些变量无法被垃圾回收机制回收。如果闭包长时间存在,而其中引用的变量又占用较大的内存空间,可能会造成内存泄漏的问题。因此,在使用闭包时需要注意及时释放不再需要的闭包。

需要注意的是,虽然闭包可以延长变量的生命周期,但过度使用闭包或者使用不当可能会导致内存泄漏和性能问题。因此,在使用闭包时需要谨慎考虑其对变量生命周期的影响,确保合理管理和释放闭包中的资源。


闭包的优点和挑战

闭包带来的优点

闭包在 JavaScript 中带来了一些重要的优点,包括封装性和数据私有性。下面是对这些优点的详细探讨:

  1. 封装性(Encapsulation): 闭包可以实现函数和数据的封装,将它们组合在一起形成一个独立的单元。通过这种封装性,闭包可以隐藏内部的实现细节,只暴露必要的接口给外部使用。这种封装性使得代码更加模块化、可维护性更高,并且减少了全局命名空间的冲突。
  2. 数据私有性(Data Privacy): 闭包可以创建私有变量和私有函数,即只能在闭包内部访问和修改的变量和函数。这种数据私有性可以防止外部代码直接访问和篡改闭包中的数据,只能通过闭包提供的公共接口来间接操作。这样可以保护数据的完整性和安全性,避免不必要的外部干扰。
  3. 高级功能的实现: 闭包可以帮助实现一些高级功能,例如函数柯里化(Currying)、函数记忆(Function Memoization)和模块化等。通过利用闭包的特性,可以方便地定义和使用这些功能,提高代码的灵活性和可重用性。
  4. 保持状态(State Retention): 闭包可以保持函数的状态,即使函数执行完毕后依然保留该状态。这种能力使得函数在不同的调用之间共享数据和状态,可以实现一些需要保持状态的操作,如计数器、缓存等。
  5. 高效的事件处理: 闭包非常适合用于事件处理,特别是在多个事件处理程序中共享数据的场景下。通过将共享的数据保存在闭包中,每个事件处理程序都可以访问和修改这些数据,从而实现更灵活和高效的事件处理逻辑。

闭包可能带来的挑战

闭包在 JavaScript 中的使用可能会带来一些挑战,包括内存泄漏和性能问题。下面是对这些挑战的讨论:

  1. 内存泄漏: 闭包中的函数引用了外部函数的变量,这意味着外部函数中的变量不会被垃圾回收机制回收,即使它们已经不再需要。如果闭包长时间存在,并且其中引用的变量占用较大内存空间,就会导致内存泄漏的问题。为避免内存泄漏,我们应当谨慎管理闭包的生命周期,确保在不再需要时及时释放闭包。
  2. 性能问题: 由于闭包会持有对外部变量的引用,每次访问外部变量都需要在作用域链中查找,这可能导致性能下降。尤其是在循环中创建闭包时,闭包的创建和销毁过程可能会变得非常频繁,对性能产生负面影响。在性能敏感的场景中,应当谨慎使用闭包,尽可能减少闭包的创建和引用的变量数量,以提高代码执行效率。
  3. 内存消耗: 闭包会持有对外部变量的引用,导致这些变量无法被垃圾回收。如果闭包中引用的变量占用大量内存空间,就会增加整体的内存消耗。在处理大量数据或长时间运行的场景中,应当注意合理管理闭包,避免过度消耗内存。
  4. 难以追踪和调试: 使用闭包时,由于闭包内部可以访问外部作用域的变量,可能会增加代码的复杂性,使得调试变得更加困难。尤其是在多层嵌套的闭包中,追踪变量的来源和调试错误可能会变得更加复杂。

为了应对这些挑战,我们应当谨慎使用闭包,并且遵循一些最佳实践,如限制闭包的作用域范围、避免循环中创建闭包、及时释放不再需要的闭包等。此外,在开发过程中使用性能工具和内存分析工具来检测和解决潜在的问题也是很重要的。

使用闭包的注意事项

使用闭包时,以下是一些注意事项,可以帮助我们避免潜在的问题:

  1. 避免循环中创建闭包: 在循环中创建闭包可能导致性能问题,因为闭包的创建和销毁过程会频繁发生。可以通过使用立即执行函数表达式或函数绑定来解决这个问题,确保在循环中不会创建新的闭包。
  2. 尽量减少闭包引用的外部变量数量: 闭包会持有对外部变量的引用,因此闭包引用的变量越多,内存消耗也越大。在创建闭包时,尽量避免引用过多的外部变量,只引用必要的变量,以减少内存消耗。
  3. 关注闭包的生命周期: 确保及时释放不再需要的闭包,避免造成内存泄漏。在不再需要闭包时,将其引用置为 null,使得垃圾回收机制可以回收相关的内存空间。
  4. 使用模块模式: 模块模式是一种常见的使用闭包的方式,可以实现封装性和数据私有性。通过使用模块模式,可以明确指定哪些数据和函数对外可见,提高代码的可维护性。
  5. 谨慎使用全局变量: 当闭包中引用了全局变量时,可能会导致全局命名空间的冲突和内存泄漏。因此,在闭包中尽量避免引用过多的全局变量,尽量将需要共享的数据和函数封装在模块中。
  6. 追踪和调试: 由于闭包会增加代码的复杂性,追踪变量的来源和调试错误可能会变得更加困难。使用浏览器的开发者工具和调试器来帮助追踪和调试闭包相关的问题。
  7. 在性能敏感的场景中审慎使用闭包: 在对性能要求较高的场景中,要谨慎使用闭包,尽量减少闭包的创建和引用的变量数量,以提高代码的执行效率。

通过遵循这些最佳实践和注意事项,我们可以更好地使用闭包,减少潜在问题的出现,并提升代码的可读性、可维护性和性能。


闭包使用案例和实际场景

闭包在 JavaScript 中的使用非常灵活,可以应用于各种有趣的场景。以下是一些有趣的闭包使用案例和实际场景:

  1. 私有变量和封装: 闭包可以创建私有变量,通过将变量保存在闭包的作用域中,实现数据的封装和隐藏。这种模式可用于创建模块、插件或库,确保外部代码无法直接访问内部变量。
  2. 计数器和唯一标识符生成器: 闭包可以用于创建计数器函数,每次调用函数时自增计数。这在需要跟踪某个操作次数或生成唯一标识符时非常有用。
  3. 缓存机制: 闭包可以用于创建缓存函数,将函数的计算结果缓存起来,避免重复计算。这对于计算密集型操作或需要频繁调用且结果稳定的函数来说,能够提高性能。
  4. 事件处理器: 闭包经常用于创建事件处理器,在事件触发时执行特定的逻辑。闭包可以捕获事件处理器中所需的变量,并保持其状态。
  5. 循环中的异步操作: 在循环中使用闭包可以解决异步操作中的问题。典型的例子是在循环中使用闭包来处理异步请求,并确保每个请求都能正确处理。
  6. 模拟私有方法: 由于 JavaScript 中没有真正的私有方法,但使用闭包可以模拟私有方法。通过在对象中创建闭包作为方法,可以将外部无法直接访问的方法包装在闭包中,实现私有性。
  7. 实现记忆化: 闭包可以用于实现记忆化,即将函数的输入和输出进行缓存,以便在相同输入的情况下直接返回缓存的结果,提高函数执行效率。

这些案例只是闭包在实际应用中的几个例子,闭包的灵活性使其适用于各种场景。通过合理运用闭包,我们可以更好地组织和管理代码,提高代码的可读性和可维护性,并实现一些有趣和强大的功能。

学习资源推荐

  • 文章和教程:
    MDN Web 文档:MDN 提供了详细的闭包介绍和示例,是一个很好的起点。
    JavaScript 高级概念:闭包:阮一峰的博客文章,对闭包进行了深入讲解,适合进一步理解闭包的原理和应用。
    廖雪峰的 JavaScript 教程:廖雪峰的 JavaScript 教程也涵盖了闭包的内容,以简洁明了的方式介绍了闭包的原理和使用方法。
    慕课网:慕课网是国内知名的在线教育平台,提供了大量与 JavaScript 闭包相关的视频教程,如《JavaScript深入浅出》、《JavaScript进阶篇》等。
    尚硅谷:尚硅谷是国内知名的IT培训机构,他们的网站上有大量 JavaScript 相关的教程和课程,包括闭包的讲解。

  • 视频教程:
    JavaScript Closures:Kyle Robinson Young 的视频教程,通过实际案例演示了闭包的功能和实际应用。
    但需要注意,这边需要一个加速器,否则无法打开国外的网站,这就需要各位科学上网了。

  • 书籍:
    《JavaScript高级程序设计》(第4版):这本由 Nicholas C. Zakas 所著的书籍是学习 JavaScript 的经典之作,其中有一章专门讲解了函数和闭包。
    《你不知道的JavaScript(上卷)》:这本由 Kyle Simpson 所著的系列图书中,第一卷涵盖了 JavaScript 的作用域和闭包,对深入理解闭包非常有帮助。

除了这些资源之外,还建议你通过实际编写代码和阅读开源项目的源代码来进一步学习闭包。实践中遇到的问题和案例可以帮助加深对闭包的理解和应用。

记住,理解闭包需要时间和实践。持续阅读和编写代码将帮助你更好地掌握闭包的概念和技巧。

在这里插入图片描述


相关文章:

前端(十三)——JavaScript 闭包的奥秘与高级用法探索

&#x1f636;博主&#xff1a;小猫娃来啦 &#x1f636;文章核心&#xff1a;深入理解 JavaScript 中的闭包 文章目录 不理解闭包&#xff1f;这玩意很难&#xff1f;闭包的定义与原理闭包是什么创建一个闭包 闭包的应用场景闭包与作用域闭包与作用域之间的关系全局作用域、函…...

面试-快速学习计算机网络-UDP/TCP

1. OSI四层和七层映射 区别&#xff1a; 应用层&#xff0c;表示层&#xff0c;会话层合并为了应用层数据链路层和物理层合并为了网络接口层 2. TCP和UDP的区别&#xff1f; 总结&#xff1a; 1 . TCP 向上层提供面向连接的可靠服务 &#xff0c;UDP 向上层提供无连接不可靠服…...

爱校对如何帮助企业和博客主提高在线可见性?

在数字化时代&#xff0c;内容质量已经成为增强在线曝光率的关键因素。企业和博客主经常面临挑战&#xff0c;如何制作高质量、无误的内容以吸引更多的在线用户。此文将详细分析“爱校对”如何帮助用户优化内容&#xff0c;从而提高在线可见性。 1.互联网内容的挑战 搜索引擎…...

MATLAB中xlsread函数用法

目录 语法 说明 示例 将工作表读取到数值矩阵 读取元胞的范围 读取列 请求数值、文本和原始数据 对工作表执行函数 请求自定义输出 局限性 xlsread函数的功能是读取Microsoft Excel 电子表格文件 语法 num xlsread(filename) num xlsread(filename,sheet) num x…...

Prisma.js:JavaScript中的基于代码的ORM

​Prisma是一种流行的用于服务器端JavaScript和TypeScript的数据映射层&#xff08;ORM&#xff09;。它的核心目的是简化和自动化数据在存储和应用程序代码之间的传输方式。Prisma支持各种数据存储&#xff0c;并为数据持久化提供了一个强大而灵活的抽象层。通过这个基于代码的…...

解决问题:在cocos create中如何从b文件调用到a文件里用CC.resource.load动态加载的图集

目录 1.在a文件中定义一个公共的变量存储动态加载的图集 2.在a.js中添加一个静态方法&#xff0c;返回动态加载的图集 3.在b.js中使用a.js中定义的静态方法获取图集&#xff0c;并使用它 假设a文件中用CC.resource.load动态加载了一张图集&#xff0c;b文件需要使用这张图集&am…...

分布式 - 消息队列Kafka:Kafka 消费者消费位移的提交方式

文章目录 1. 自动提交消费位移2. 自动提交消费位移存在的问题&#xff1f;3. 手动提交消费位移1. 同步提交消费位移2. 异步提交消费位移3. 同步和异步组合提交消费位移4. 提交特定的消费位移5. 按分区提交消费位移 4. 消费者查找不到消费位移时怎么办&#xff1f;5. 如何从特定…...

如何利用 ChatGPT 进行自动数据清理和预处理

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 ChatGPT 已经成为一把可用于多种应用的瑞士军刀&#xff0c;并且有大量的空间将 ChatGPT 集成到数据科学工作流程中。 如果您曾经在真实数据集上训练过机器学习模型&#xff0c;您就会知道数据清理和预…...

PHP“牵手”淘宝商品评论数据采集方法,淘宝API接口申请指南

淘宝天猫商品评论数据接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在电商平台的开发中&#xff0c;详情接口API是非常常用的 API&#xff0c;因此本文将详细介绍详情接口 API 的使用…...

你更喜欢哪一个:VueJS 还是 ReactJS?

观点列表&#xff1a; 1、如果你想在 HTML 中使用 JS&#xff0c;请使用 Vue&#xff1b; 如果你想在 JS 中使用 HTML&#xff0c;请使用 React。 当然&#xff0c;如果您希望在 JS 中使用 HTML&#xff0c;请将 Vue 与 JSX 结合使用。 2、Svelte&#xff1a;我喜欢它&#…...

PyTorch学习笔记(十六)——利用GPU训练

一、方式一 网络模型、损失函数、数据&#xff08;包括输入、标注&#xff09; 找到以上三种变量&#xff0c;调用它们的.cuda()&#xff0c;再返回即可 if torch.cuda.is_available():mynn mynn.cuda() if torch.cuda.is_available():loss_function loss_function.cuda(…...

【实战】十一、看板页面及任务组页面开发(三) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十五)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…...

金额千位符自定义指令

自定义指令文件 moneyFormat.js /*** v-money 金额千分位转换*/export default {inserted: inputFormatter({// 格式化函数formatter(num, util) {if(num null || num || num undefined || typeof(num) undefined){return }if(util 万元 || util 万){return formatMone…...

请不要用 JSON 作为配置文件,使用JSON做配置文件的缺点

我最近关注到有的项目使用JSON作为配置文件。我觉得这不是个好主意。 这不是JSON的设计目的&#xff0c;因此也不是它擅长的。JSON旨在成为一种“轻量级数据交换格式”&#xff0c;并声称它“易于人类读写”和“易于机器解析和生成”。 作为一种数据交换格式&#xff0c;JSON是…...

Hadabot:从网络浏览器操作 ROS2 远程控制器

一、说明 Hadabot Hadabot是一个学习ROS2和机器人技术的机器人套件。使用 Hadabot&#xff0c;您将能够以最小的挫败感和恐吓来构建和编程物理 ROS2 机器人。Hadabot套件目前正在开发中。它将仅针对ROS2功能&#xff0c;并强调基于Web的用户界面。 随着开发的进展&a…...

Kotlin 协程

Kotlin 协程&#xff08;Coroutines&#xff09;是一种轻量级的并发编程解决方案&#xff0c;旨在简化异步操作和多线程编程。它提供了一种顺序和非阻塞的方式来处理并发任务&#xff0c;使得代码可以更加简洁和易于理解。Kotlin 协程通过提供一套高级 API&#xff0c;使并发代…...

maven 从官网下载指定版本

1. 进入官网下载页面 Maven – Download Apache Maven 点击下图所示链接 2. 进入文件页&#xff0c;选择需要的版本 3. 选binaries 4. 选文件&#xff0c;下载即可...

数据结构---串(赋值,求子串,比较,定位)

目录 一.初始化 顺序表中串的存储 串的链式存储 二.赋值操作&#xff1a;将str赋值给S 链式表 顺序表 三.复制操作&#xff1a;将chars复制到str中 链式表 顺序表 四.判空操作 链式表 顺序表 五.清空操作 六.串联结 链式表 顺序表 七.求子串 链式表 顺序表…...

WPF CommunityToolkit.Mvvm

文章目录 前言ToolkitNuget安装简单使用SetProperty&#xff0c;通知更新RealyCommandCanExecute 新功能&#xff0c;代码生成器ObservablePropertyNotifyCanExecuteChangedForRelayCommand其他功能对应关系 NotifyPropertyChangedFor 前言 CommunityToolkit.Mvvm&#xff08;…...

Vue开发中如何解决国际化语言切换问题

Vue开发中如何解决国际化语言切换问题 引言&#xff1a; 在如今的全球化时代&#xff0c;应用程序的国际化变得越来越重要。为了让不同地区的用户能够更好地使用应用程序&#xff0c;我们需要对内容进行本地化&#xff0c;以适应不同语言和文化环境。对于使用Vue进行开发的应用…...

基于springboot+vue的流动人口登记系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...

Stable Diffusion的使用以及各种资源

Stable Diffsuion资源目录 SD简述sd安装模型下载关键词&#xff0c;描述语句插件管理controlNet自己训练模型 SD简述 Stable Diffusion是2022年发布的深度学习文本到图像生成模型。它主要用于根据文本的描述产生详细图像&#xff0c;尽管它也可以应用于其他任务&#xff0c;如…...

Redis 分布式锁的实现方式

一般来说&#xff0c;在对数据进行“加锁”时&#xff0c;程序首先需要通过获取&#xff08;acquire&#xff09;锁来得到对数据排他性访问的能力&#xff0c;然后才能对数据执行一系列操作&#xff0c;最后还要将锁释放&#xff08;release&#xff09;给其他程序。 对于能够…...

VMware上搭建的虚拟机突然本地无法连接服务器

长时间没有使用VMware 虚拟机了&#xff0c;今天突然登录上去&#xff0c;启动虚拟服务器后发现本地等不了了&#xff0c; 经过排查发现是开启了&#xff1a;VirtualBox Host-Only Network 关闭之后就本机就可以直连服务器了...

JDBC回顾

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 JDBC回顾 前言一、JDBC1.JDBC是什么&#xff1f;2.如何使用&#xff1f;&#xff08;1&#xff09;注册驱动&#xff08;2&#xff09;获取连接&#xff08;3&#xff09;操作…...

mq 消息队列 mqtt emqx ActiveMQ RabbitMQ RocketMQ

省流&#xff1a; 十几年前&#xff0c;淘宝的notify&#xff0c;借鉴ActiveMQ。京东的ActiveMQ集群几百台&#xff0c;后面改成JMQ。 Linkedin的kafka&#xff0c;因为是scala&#xff0c;国内很多人不熟。淘宝的人把kafka用java写了一遍&#xff0c;取名metaq&#xff0c;后…...

沃尔玛卖家必看!解决订单被Kan、Feng号问题的终极方案!

近期有很多沃尔玛卖家和工作室联系到我提到说在沃尔玛平台上下单&#xff0c;买家号出现副款义常订单被k掉&#xff0c;是什么原因、我们该如何去解决呢&#xff1f; 以下是一些可能导至你的测评订单被k单的原因&#xff1a; 1.技术问题&#xff1a;有时&#xff0c;网站或系…...

浅谈日常使用的 Docker 底层原理-三大底座

适合的读者&#xff0c;对Docker有过简单了解的朋友&#xff0c;想要进一步了解Docker容器的朋友。 前言 回想我这两年&#xff0c;一直都是在使用 Docker&#xff0c;看过的视频、拜读过的博客&#xff0c;大都是在介绍 Docker 的由来、使用、优点和发展趋势&#xff0c;但对…...

前端面试:【DOM】编织网页的魔法

嘿&#xff0c;亲爱的代码魔法师&#xff01;在JavaScript的奇幻世界里&#xff0c;有一项强大的技能&#xff0c;那就是DOM操作。DOM&#xff08;文档对象模型&#xff09;操作允许你选择、修改和创建网页元素&#xff0c;就像是在编织一个魔法的网页。 1. 什么是DOM&#xff…...

基于MATLAB开发AUTOSAR软件应用层Code mapping专题-part 2 Inport和Outports 标签页介绍

上篇我们介绍了Function页的内容,这篇我们介绍Inports和Outports页的内容,这里我们再次强调一个概念,code mapping是以simulink的角度去看的,就是先要在模型中建立simulink模块,在code mapping里映射他要对应的autosar的元素,之后生成代码时的c语言的名字是以Autosar的元…...

第9步---MySQL的索引和存储引擎

第9步---MySQL的索引和存储引擎 1.索引 1.1分类 索引可以快速的找出具有特定值的行。不用从头开始进行寻找了。 类别 hash和btree hash 根据字段值生生成一个hash的值 快速的进行定位到对应的行的值 可能会出现相同的值&#xff0c;找到对应的空间会出现对应的值 btree树…...

Numpy入门(3)—线性代数

线性代数 线性代数&#xff08;如矩阵乘法、矩阵分解、行列式以及其他方阵数学等&#xff09;是任何数组库的重要组成部分&#xff0c;NumPy中实现了线性代数中常用的各种操作&#xff0c;并形成了numpy.linalg线性代数相关的模块。本节主要介绍如下函数&#xff1a; diag&am…...

php的openssl_encrypt是不是自动做了PKCS5Padding?

在PHP中&#xff0c;openssl_encrypt函数默认使用的是PKCS7填充&#xff08;不是PKCS5填充&#xff09;。PKCS7填充实际上是PKCS5填充的扩展&#xff0c;用于对不同块大小的数据进行填充。 当你使用openssl_encrypt函数进行加密时&#xff0c;如果你没有显式指定填充模式和填充…...

在本地创建repository及上传至github

文章目录 本地管理设定git的用户名与邮箱初始化添加修改提交修改设定分支问题一:error: insufficient permission for adding an object... 数据同步创建SSH keys创建并关联远程仓库上传改动至github问题二:Failed to connect to github.com port 443: Connection timed out问题…...

情人节特别定制:多种语言编写动态爱心网页(附完整代码)

写在前面案例1&#xff1a;HTML Three.js库案例2&#xff1a;HTML CSS JavaScript案例3&#xff1a;Python环境 Flask框架结语 写在前面 随着七夕节的临近&#xff0c;许多人都在寻找独特而令人难忘的方式来表达爱意。在这个数字时代&#xff0c;结合创意和技术&#xff0…...

Docker mysql主从同步安装

1. 构建master实例 docker run -p 3307:3306 --name mysql-master \ -v /mydata/mysql-master/log:/var/log/mysql \ -v /mydata/mysql-master/data:/var/lib/mysql \ -v /mydata/mysql-master/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORDroot \ -d mysql:5.7 2. 构建master配置…...

docker update 命令

docker update 更新一个或多个容器的配置。官方文档 用法 $ docker update [OPTIONS] CONTAINER [CONTAINER...]请参阅选项部分OPTIONS&#xff0c;了解此命令可用的概述。 描述 该docker update命令动态更新容器配置。您可以使用此命令来防止容器消耗 Docker 主机的过多资…...

阻塞和挂起的区别和联系

阻塞和挂起是进程两种不同的状态&#xff0c;其描述如下&#xff1a; 阻塞&#xff1a;正在执行的进程由于发生某时间&#xff08;如I/O请求、申请缓冲区失败等&#xff09;暂时无法继续执行。此时引起进程调度&#xff0c;OS把处理机分配给另一个就绪进程&#xff0c;而让受阻…...

水力发电厂测量装置配置选型及厂用电管理系统

《水力发电厂测量装置配置设计规范》对水电厂的测量装置配置做了详细要求和指导。测量装置是水力发电厂运行监测的重要环节&#xff0c;水电厂的测量主要分为电气量测量和非电量测量。电气测量指使用电的方式对电气实时参数进行测量&#xff0c;包括电流、电压、频率、功率因数…...

【RabbitMQ】RabbitMQ整合SpringBoot案例

文章目录 1、前情提要【RabbitMQ】2、RabbitMQ-SpringBoot案例 -fanout模式2.1 实现架构总览2.2 具体实现2.2.1生产者2.2.1消费者 1、前情提要【RabbitMQ】 【RabbitMQ】消息队列-RabbitMQ篇章 RabbitMQ实现流程 2、RabbitMQ-SpringBoot案例 -fanout模式 2.1 实现架构总览…...

如何在window下cmd窗口执行linux指令?

1.Git&#xff1a;https://git-scm.com/downloads(官网地址) 2.根据自己的实际路径,添加两个环境变量 3.重启电脑...

c++基础系列:字符串、向量和数组

字符串、向量和数组 命名空间的using声明 目前用到的库函数基本上都属于命名空间std&#xff1b;通过using声明&#xff08;using declaration&#xff09;实现更简单的途径使用到命名空间中的成员。 标准库类型string string表示可变长的字符序列&#xff0c;必须先包含st…...

docker 05(dockerfile)

一、docker镜像原理 镜像可以复用 二、容器转镜像 将容器保存为镜像[参考] docker commit -a -m 现有容器ID 保存后的名称&#xff1a;版本号 -a :提交的镜像作者&#xff1b; -c :使用Dockerfile指令来创建镜像&#xff1b; -m :提交时的说明文字&#xff1b; -p :…...

PostMan 测试项目是否支持跨域

使用PostMan可以方便快速的进行跨域测试。 只需要在请求头中手动添加一个Origin的标头&#xff0c;声明需要跨域跨到的域&#xff08;IP&#xff1a;端口&#xff09;就行&#xff0c;其余参数PostMan会自动生成。添加此标头后&#xff0c;请求会被做为一条跨域的请求来进行处…...

jsp 协同过滤 图书管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 协同过滤 图书管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为My…...

商城-学习整理-高级-商城业务-商品上架es(十)

目录 一、商品上架1、sku在ES中存储模型分析2、nested数据类型场景3、构造基本数据&#xff08;商品上架&#xff09; 二、首页1、项目介绍2、整合thymeleaf&#xff08;spring-boot下模板引擎&#xff09;渲染页面3、页面修改不重启服务器实时更新4、渲染二级三级数据 三、搭建…...

【水文学法总结】河道内生态流量计算方法(含MATLAB实现代码)

生态流量&#xff08;Ecological Flow, EF&#xff09; 是指维持河道内生态环境所需要的水流流量。生态流量计算方法众多&#xff0c;主要分为水文学方法、栖息地模拟法、水力学方法、整体法等&#xff0c;各方法多用于计算维持河道生态平衡的最小生态流量&#xff08;Minimum …...

特斯拉Model 3的七年狂飙

‍ 作者 | 张祥威 编辑 | 德新 发布一周拿下32万张订单&#xff0c;之后用时五年&#xff0c;交付量突破100万辆。粗略计算&#xff0c;自2016年发布至今&#xff0c;特斯拉Model 3已交付超150万辆。 放眼新能源赛道&#xff0c;如此战绩 别无二家。 Model 3踩中纯电动车的…...

物流签收异常,财务对账复杂,怎么解决?

电子商务行业的蓬勃发展为人们的购物体验带来了巨大的便利&#xff0c;然而&#xff0c;随之而来的物流签收异常和财务对账复杂问题却给电商企业的财务部门带来了一系列困扰。 每天大量的订单和货物流转&#xff0c;不可避免地导致了物流签收数据与财务记录之间的不一致和差异…...

docker之镜像与数据卷

镜像 简介 1.镜像是一种轻量级、可执行的独立软件包&#xff0c;用来打包软件运行环境和基于环境开发的软件&#xff0c;他包含运行某个软件所需的所有内容&#xff0c;包括代码、运行时库、环境变量、配置文件 2.将所有的应用和环境11&#xff0c;直接打包成docker镜像&…...