闭包的示例

什么是封包? (What are Closures?)

A closure is the combination of a function and the lexical environment (scope) within which that function was declared. Closures are a fundamental and powerful property of Javascript. This article discusses the ‘how’ and ‘why’ about Closures:

闭包是函数和在其中声明该函数的词法环境(范围)的组合。 闭包是Javascript的基本功能。 本文讨论了闭包的“方式”和“原因”:

(Example)

//we have an outer function named walk and an inner function named flyfunction walk (){var dist = '1780 feet';function fly(){console.log('At '+dist);}return fly;
}var flyFunc = walk(); //calling walk returns the fly function which is being assigned to flyFunc
//you would expect that once the walk function above is run
//you would think that JavaScript has gotten rid of the 'dist' varflyFunc(); //Logs out 'At 1780 feet'
//but you still can use the function as above
//this is the power of closures

另一个例子 (Another Example)

function by(propName) {return function(a, b) {return a[propName] - b[propName];}
}const person1 = {name: 'joe', height: 72};
const person2 = {name: 'rob', height: 70};
const person3 = {name: 'nicholas', height: 66};const arr_ = [person1, person2, person3];const arr_sorted = arr_.sort(by('height')); // [ { name: 'nicholas', height: 66 }, { name: 'rob', height: 70 },{ name: 'joe', height: 72 } ]

The closure ‘remembers’ the environment in which it was created. This environment consists of any local variables that were in-scope at the time the closure was created.

闭包“记住”创建它的环境。 此环境由创建关闭时在范围内的所有局部变量组成。

function outside(num) {var rememberedVar = num; // In this example, rememberedVar is the lexical environment that the closure 'remembers'return function inside() { // This is the function which the closure 'remembers'console.log(rememberedVar)}
}var remember1 = outside(7); // remember1 is now a closure which contains rememberedVar = 7 in its lexical environment, and //the function 'inside'
var remember2 = outside(9); // remember2 is now a closure which contains rememberedVar = 9 in its lexical environment, and //the function 'inside'remember1(); // This now executes the function 'inside' which console.logs(rememberedVar) => 7
remember2(); // This now executes the function 'inside' which console.logs(rememberedVar) => 9

Closures are useful because they let you ‘remember’ data and then let you operate on that data through returned functions. This allows javascript to emulate private methods that are found in other programming languages. Private methods are useful for restricting access to code as well as managing your global namespace.

闭包很有用,因为它们可以让您“记住”数据,然后让您通过返回的函数对数据进行操作。 这允许javascript模拟其他编程语言中找到的私有方法。 私有方法对于限制对代码的访问以及管理全局名称空间很有用。

私有变量和方法 (Private variables and methods)

Closures can also be used to encapsulate private data/methods. Take a look at this example:

闭包也可以用于封装私有数据/方法。 看一下这个例子:

const bankAccount = (initialBalance) => {const balance = initialBalance;return {getBalance: function() {return balance;},deposit: function(amount) {balance += amount;return balance;},};
};const account = bankAccount(100);account.getBalance(); // 100
account.deposit(10); // 110

In this example, we won’t be able to access balance from anywhere outside of the bankAccount function, which means we’ve just created a private variable. Where’s the closure? Well, think about what bankAccount() is returning. It actually returns an Object with a bunch of functions inside it, and yet when we call account.getBalance(), the function is able to “remember” its initial reference to balance. That is the power of the closure, where a function “remembers” its lexical scope (compile time scope), even when the function is executed outside that lexical scope.

在此示例中,我们将无法从bankAccount函数之外的任何位置访问balance ,这意味着我们仅创建了一个私有变量。 封闭在哪里? 好吧,考虑一下bankAccount()返回什么。 实际上,它返回一个内部带有一堆函数的Object,但是当我们调用account.getBalance() ,该函数能够“记住”其对balance初始引用。 这就是闭包的强大之处,即使函数在该词法范围之外执行,函数也“记住”其词法范围(编译时范围)。

模拟块作用域变量。 (Emulating block-scoped variables.)

Javascript did not have a concept of block-scoped variables. Meaning that when defining a variable inside a forloop for example, this variable is visible from outside the forloop as well. So how can closures help us solve this problem ? Let’s take a look.

Javascript没有块范围变量的概念。 这意味着例如在forloop内定义变量时,也可以从forloop外部看到此变量。 那么闭包如何帮助我们解决这个问题呢? 让我们来看看。

var funcs = [];for(var i = 0; i < 3; i++){funcs[i] = function(){console.log('My value is ' + i);  //creating three different functions with different param values.}}for(var j = 0; j < 3; j++){funcs[j]();             // My value is 3// My value is 3// My value is 3}

Since the variable i does not have block-scope, it’s value within all three functions was updated with the loop counter and created malicious values. Closure can help us solve this issue by creating a snapshot of the environment the function was in when it was created, preserving its state.

由于变量i没有块作用域,因此使用循环计数器更新了这三个函数中的值并创建了恶意值。 闭包可以通过创建函数创建时所在的环境的快照,并保留其状态来帮助我们解决此问题。

var funcs = [];var createFunction = function(val){return function() {console.log("My value: " + val);};}for (var i = 0; i < 3; i++) {funcs[i] = createFunction(i);}for (var j = 0; j < 3; j++) {funcs[j]();                 // My value is 0// My value is 1// My value is 2}

The late versions of javascript es6+ have a new keyword called let which can be used to give the variable a blockscope. There are also many functions (forEach) and entire libraries (lodash.js) that are dedicated to solve such problems as the ones explained above. They can certainly boost your productivity, however it remains extremely important to have knowledge of all these issues when attempting to create something big.

javascript es6 +的较新版本有一个名为let的新关键字,可用于为变量赋予功能块。 还有许多函数(forEach)和整个库(lodash.js)专门用于解决上述问题。 它们当然可以提高您的生产率,但是在尝试创建大型产品时了解所有这些问题仍然非常重要。

Closures have many special applications that are useful when creating large javascript programs.

闭包有许多特殊的应用程序,在创建大型javascript程序时非常有用。

  1. Emulating private variables or encapsulation模拟私有变量或封装
  2. Making Asynchronous server side calls进行异步服务器端调用
  3. Creating a block-scoped variable.创建一个块作用域变量。

模拟私有变量。 (Emulating private variables.)

Unlike many other languages, Javascript does not have a mechanism which allows you to create encapsulated instance variables within an object. Having public instance variables can cause a lot of problems when building medium to large programs. However with closures, this problem can be mitigated.

与许多其他语言不同,Javascript没有允许您在对象内创建封装的实例变量的机制。 在构建中型到大型程序时,拥有公共实例变量会导致很多问题。 但是,使用闭包可以缓解此问题。

Much like in the previous example, you can build functions which return object literals with methods that have access to the object’s local variables without exposing them. Thus, making them effectively private.

与上一个示例非常相似,您可以构建函数,这些函数使用可以访问对象的局部变量而无需暴露它们的方法来返回对象文字。 因此,将它们有效地私有化。

Closures can also help you manage your global namespace to avoid collisions with globally shared data. Usually all global variables are shared between all scripts in your project, which will definitely give you alot of trouble when building medium to large programs. That is why library and module authors use closures to hide an entire module’s methods and data. This is called the module pattern, it uses an immediately invoked function expression which exports only certain functionality to the outside world, significantly reducing the amount of global references.

闭包还可以帮助您管理全局名称空间,以避免与全局共享数据发生冲突。 通常,所有全局变量都在项目中的所有脚本之间共享,这在构建中型到大型程序时肯定会给您带来很多麻烦。 这就是为什么库和模块作者使用闭包来隐藏整个模块的方法和数据的原因。 这称为模块模式,它使用立即调用的函数表达式,该函数表达式仅将某些功能导出到外界,从而大大减少了全局引用的数量。

Here’s a short sample of a module skeleton.

这是模块骨架的简短示例。

var myModule = (function() = {let privateVariable = 'I am a private variable';let method1 = function(){ console.log('I am method 1'); };let method2 = function(){ console.log('I am method 2, ', privateVariable); };return {method1: method1,method2: method2}
}());myModule.method1(); // I am method 1
myModule.method2(); // I am method 2, I am a private variable

Closures are useful for capturing new instances of private variables contained in the ‘remembered’ environment, and those variables can only be accessed through the returned function or methods.

闭包对于捕获“记住的”环境中包含的私有变量的新实例很有用,这些变量只能通过返回的函数或方法进行访问。

向量 (Vectors)

A vector is perhaps the most simple type of collection in Clojure. You can think of it like an array in Javascript. Let’s define a simple vector:

向量可能是Clojure中最简单的集合类型。 您可以将其视为Javascript中的数组。 让我们定义一个简单的向量:

(def a-vector [1 2 3 4 5])
;; Alternatively, use the vector function:
(def another-vector (vector 1 2 3 4 5))
;; You can use commas to separate items, since Clojure treats them as whitespace.
(def comma-vector [1, 2, 3, 4, 5])

You’ll see that it uses square brackets, just like an array in JS. Since Clojure, like JS, is dynamically typed, vectors can hold elements of any type, including other vectors.

您会看到它使用方括号,就像JS中的数组一样。 由于Clojure与JS类似,是动态类型化的,因​​此向量可以保存任何类型的元素,包括其他向量。

(def mixed-type-vector [1 "foo" :bar ["spam" 22] #"^baz$"])

向矢量添加项目 (Adding items to a vector)

You can append items to a vector using conj. You can also prepend to a list using into, but note that into is intended for merging two vectors, so both its arguments must be vectors, and using into is slower than using conj.

您可以使用conj将项目附加到向量。 您也可以在前面加上使用列表into ,但要注意, into适用于合并两个载体,所以它的两个参数必须是向量,并使用into比使用较慢的conj

(time (conj [1 2] 3))
; => "Elapsed time: 0.032206 msecs"
;    [1 2 3]
(time (into [1] [2 3]))
; => "Elapsed time: 0.078499 msecs"
;    [1 2 3]

IDEOne it!

IDEOne!

从向量中检索项目 (Retrieving items from a vector)

You can retrieve items from a vector using get. This is equivalent to using bracket notation to access items in an array in many imperative languages. Items in a vector are 0-indexed, counting from the left.

您可以使用get从向量中检索项目。 这等效于使用括号符号以许多命令式语言访问数组中的项目。 向量中的项从左开始数为0索引。

var arr = [1, 2, 3, 4, 5];
arr[0];
// => 1

In Clojure, this would be written like so:

在Clojure中,将这样写:

(def a-vector [1 2 3 4 5])
(get a-vector 0)
; => 1

You can also give get a default value, if you give it an index that isn’t in the array.

你也可以给get一个默认值,如果你给它一个指标,是不是在数组中。

;; the list doesn't have 2147483647 elements, so it'll return a string instead.
(get a-vector 2147483646 "sorry, not found!")
; => "sorry, not found!"

将其他集合转换为向量 (Converting other collections into vectors)

Non-vector data structures can be converted into vectors using the vec function. With hashmaps, this produces a 2D vector containing pairs of keys and values.

可以使用vec函数将非矢量数据结构转换为矢量。 使用哈希图,这将生成一个包含键和值对的2D向量。

(vec '(1 2 3 4 5))
; => [1 2 3 4 5]
(vec {:jack "black" :barry "white"})
; => [[:jack "black"] [:barry "white"]]

什么时候使用向量? (When to use a vector?)

A vector should be used in almost all cases if you need a collection, because they have the shortest random-access times, which makes it easy to retrieve items from a vector. Note that vectors are ordered. If order doesn’t matter, it may be better to use a set. Also note that vectors are designed for appending items; if you need to prepend items, you might want to use a list.

如果需要集合,几乎在所有情况下都应使用向量,因为它们具有最短的随机访问时间,这使得从向量中检索项目变得容易。 请注意,向量是有序的。 如果顺序无关紧要,则最好使用一组。 另请注意,矢量是为附加项目而设计的; 如果您需要添加项目,则可能需要使用列表。

有关封包的更多信息: (More info on Closures:)

  • Learn JavaScript closures in six minutes

    在六分钟内学习JavaScript关闭

  • A basic guide to closures in JavaScript

    JavaScript闭包的基本指南

  • Discover the power of closures in VueJS

    在VueJS中发现封闭的力量

  • JavaScript closures explained by mailing a package

    通过邮寄包裹解释JavaScript的关闭

翻译自: https://www.freecodecamp.org/news/closures-in-javascript-explained-with-examples/

闭包的示例

闭包的示例_用示例解释JavaScript中的闭包相关推荐

  1. 让你分分钟学会Javascript中的闭包

    Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...

  2. 用一顿简餐来解释JavaScript中的状态

    by Kevin Kononenko 凯文·科诺年科(Kevin Kononenko) 用一顿简餐来解释JavaScript中的状态 (State in JavaScript explained by ...

  3. [译]Javascript中的闭包(closures)

    本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...

  4. 【javascript笔记】关于javascript中的闭包

    最开始看<javascript高级程序设计>的时候就看到了javascript中的闭包,在第七章第二节....好大概知道了,过了段时间,好了又忘了... 我们来看这本书里面关于闭包是怎么描 ...

  5. 解析面试常问题之JavaScript中的闭包概念及应用,顺便普及一下大家口中常说的内存泄漏问题

    JavaScript中的闭包是一个面试中经常被考到的问题,大家可能都对这个概念多多少少都有一些模糊的概念或者一点都不了解,那么今天就来给大家讲解一下. 公众号:前端印象 不定时有送书活动,记得关注~ ...

  6. 一篇文章把你带入到JavaScript中的闭包与高级函数

    在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. funct ...

  7. 带时间轴 歌词 示例_带有示例JavaScript externalHTML

    带时间轴 歌词 示例 In this tutorial, I will tell you about outerHTML in javascript. outerHTML provides devel ...

  8. ajax 示例_通过示例了解挥发

    ajax 示例 我们已经花了几个月的时间来稳定Plumbr中的锁定检测功能 . 在此期间,我们遇到了许多棘手的并发问题. 许多问题是独特的,但是一种特殊类型的问题一直反复出现. 您可能已经猜到了–滥用 ...

  9. mysql闭包的概念_彻底搞懂JavaScript的闭包、防抖跟节流

    最近出去面试了一下,收获颇多!!! 以前的我,追求实际,比较追求实用价值,然而最近面试,传说中的面试造火箭,工作拧螺丝,竟然被我遇到了.虽然很多知识点在实际工作中并不经常用到,但人家就是靠这个来筛选人 ...

最新文章

  1. Nginx SSL 配置
  2. java基本输入类型数据System.out.println()或System.out.print()
  3. linux ftp非隔离模式,FTP实验报告非隔离用户的使用教案.doc
  4. flutter怎么手动刷新_如何手动刷新或重新加载Flutter Firestore StreamBuilder?
  5. php二维数组拆分成字符串,PHP二维数组切割为字符串并去除重复的值
  6. 新分享一种解决ie6下PNG图片透明的方法
  7. solidity modifier函数修改器 智能合约开发知识浅学(三)
  8. fold函数_Java中使用Map and Fold进行函数式编程
  9. JavaScript 面向对象
  10. c语言全排列库函数,几种全排列的算法(C语言实现)
  11. mysql TIMESTAMP 报错
  12. Linux命令大全(常用的命令解析)
  13. Kolmogorov–Smirnov test 柯尔莫哥洛夫-斯米尔诺夫检验
  14. 视频下载工具you-get(哔哩哔哩巨好用)
  15. 利用matlab命令窗口绘制simulink仿真示波器波形的方法,利用MATLAB命令窗口绘制Simulink仿真示波器波形的方法...
  16. SiC MOSFET动态测试上位机软件使用说明
  17. 玩转StyleGan2:手把手教你安装并运行项目!
  18. 尤雨溪:Vue3 将在2022年2月7日成为新的默认版本(你准备好了吗?)
  19. 百度AI攻略:新闻摘要
  20. 电脑屏幕上计算机闪烁有框,电脑显示器有点闪烁该怎么解决

热门文章

  1. Structure from Motion 资料总结
  2. OPENWRT的串口初试
  3. 云题库进入其它章节的办法 0925
  4. python-数字数据类型-整数类型-浮点数类型-数据类型间的转换
  5. python-反射基础-hasattr-getattr-setattr
  6. javascript-运算符
  7. StringBuffer 和 StringBuilder 的 3 个区别
  8. python爬虫系列(3.8-正则的使用)
  9. 一文掌握关于Java数据结构所有知识点(欢迎一起完善) 1
  10. c#-SimHash匹配相似-算法