结束书

by William Countiss

威廉·Countiss

结束书 (Closing the Book on Closures)

JavaScript closures are an important, but notoriously confusing concept. There’s no escaping it — if you want to grow as a developer, you need to understand what closures are and how to use them.

JavaScript闭包是一个重要的概念,但众所周知令人困惑。 没有逃避之路-如果您想成长为一名开发人员,则需要了解什么是闭包以及如何使用它们。

Don’t let the fancy name scare you — once you play around with closures a bit you’ll realize that there really isn’t much to them.

不要让这个奇特的名字吓到您-一旦您对闭包进行一点操作,您就会意识到它们确实没什么用。

Let’s start with something simple:

让我们从简单的事情开始:

1 function sayGreeting(greeting) {  2  3     return function(name) {  4  5         console.log(greeting + " " + name);  6     }  7  8 }

You’ll notice right away that our function, sayGreeting, returns another function. I can do this in JavaScript because functions are considered first-class, which means that they can be passed around just like other data types such as a number, string, or boolean. This can make for some interesting syntax:

您会立即注意到我们的函数sayGreeting返回了另一个函数。 我可以在JavaScript中进行此操作,因为函数被认为是一流的,这意味着它们可以像数字,字符串或布尔值之类的其他数据类型一样传递。 这可以产生一些有趣的语法:

1 function sayGreeting (greeting) {  2  3     return function (name) {  4  5         console.log (greeting + " " + name);  6     }  7  8 }  9 sayGreeting("Hello")("William");

So what would you expect to see in the console when we run this code? Think about it for a moment and then take a look at the image below.

因此,当我们运行此代码时,您希望在控制台中看到什么? 考虑一下,然后看下面的图片。

If you guessed “Hello William”, you’re right. Go ahead and give yourself a pat on the back. Now, let’s take a closer look into why.

如果您猜到“ Hello William”,那是对的。 继续拍一下自己的背。 现在,让我们仔细研究一下原因。

sayGreeting("Hello")("William");

Remember that sayGreeting returns a function. As we mentioned earlier, functions in JavaScript are first-class, and may be passed around like any other data structure. So when sayGreeting(“Hello”) is invoked for the first time it executes and returns an anonymous function. A returned function may also be invoked, and that is why you are seeing the second set of parentheses: sayGreeting(“Hello”)(“William”)

请记住,sayGreeting 返回一个函数。 如前所述,JavaScript中的函数是一流的,并且可以像其他任何数据结构一样传递。 因此,当首次调用sayGreeting(“ Hello”)时,它将执行并返回一个匿名函数。 还可能调用返回的函数,这就是为什么您看到第二组括号的原因:sayGreeting(“ Hello”) (“ William”)

To make this a bit easier to follow let’s change the code a little by setting the first invocation to a variable:

为了使它更容易理解,我们将第一次调用设置为变量,以对代码进行一些更改:

1 function sayGreeting (greeting) {  2  3     return function(name) {  4  5         console.log(greeting + " " + name);  6     }  7  8 }  9 10 var sayHello = sayGreeting("Hello"); 11 sayHello("William");

If you run this in your console you’ll get the same result as before. But how does sayHello(“William”) know about the value of the parameter greeting from the sayGreeting function? To understand this, we’ll need to go a little deeper.

如果在控制台中运行此命令,则将获得与以前相同的结果。 但是sayHello(“ William”)如何从sayGreeting函数知道有关参数greeting的值? 要理解这一点,我们需要更深入一些。

Whenever a function is invoked, memory is set aside for that function and its contents, which stick around even after the function has finished executing. We can visualize this by wrapping the sayHello variable with a console.dir()

每当调用一个函数时,都会为该函数及其内容留出内存,即使在函数执行完毕后,这些内存仍会保留。 我们可以通过用console.dir()包装sayHello变量来可视化它

1 function sayGreeting(greeting) {  2  3     return function(name) {  4  5         console.log(greeting + " " + name);  6     }  7  8 }  9 10 var sayHello = sayGreeting("Hello"); 11 12 console.dir(sayHello); 13 sayHello("William");

You’ll see in the console that the variable sayHello is an anonymous function, and within its scope there is a Closure with a name:value pair,

您会在控制台中看到变量sayHello是一个匿名函数,并且在其范围内有一个带name:value对的C 闭环

greeting: “Hello”

问候:“你好”

This should look familiar since “greeting” is the name of the parameter of the sayGreeting(greeting) { … } function on line 1, and “Hello” was the string that we passed into it when we first invoked the function on line 10. Memory was then set aside for these values and is available as an outer reference when we invoke the function on line 13.

这应该看起来很熟悉,因为“ greeting”是第1行的sayGreeting(greeting){…}函数的参数名称,而“ Hello”是我们在第10行首次调用该函数时传递给它的字符串。然后为这些值预留了内存,当我们在第13行调用该函数时,它可用作外部引用

To help visualize this let’s write out the body of the sayHello function as it is executed on line 13.

为了使这一过程可视化,让我们在第13行执行时写出sayHello函数的主体。

1 function (name) {  2  3     console.log (greeting + " " + name);  4 }

The string “William” is passed in for the name parameter, then on line 3 console.log(greeting + “ “+ name) is executed.

为name参数传入字符串“ William”,然后在第3行console.log( greeting +““ + name )”被执行。

It then looks for the values of greeting and name.

然后,它查找greetingname的值。

Our function finds a value for name: “William”. But it doesn’t have a value for greeting. So now it’s time to go fishing, and it looks to its outer reference (where it sits in terms of lexical scope) in an attempt to find a value for greeting.

我们的函数查找名称的值:“ William”。 但这没有问候的价值。 因此,现在该钓鱼了,它查找其外部参考(在词汇范围方面),以期寻找问候的价值。

In other words, it remembers where it was explicitly written in the code, which is inside of the sayGreeting function.

换句话说,它会记住它在sayGreeting函数内部的代码中显式编写的位置。

1 function sayGreeting(greeting) {  2  3     return function(name) {  4  5         console.log(greeting + ' ' + name);  6     }  7  8 }

When it finds the value of greeting in its outer reference, we refer to this as closing in on an outer variable, and when this happens you have closure.

当它在其外部引用中找到greeting的值时,我们将其称为外部变量上封闭 ,并且当发生这种情况时,您将具有closures

That wasn’t so bad, was it?

那还不错,不是吗?

This is a very basic example, but even in complex applications, the rules remain the same. Whenever a function can’t find the value of something within itself, it will follow the scope chain all the way down (or up depending upon how you envision it) and search for that value to create the closure.

这是一个非常基本的示例,但是即使在复杂的应用程序中,规则也保持不变。 每当函数无法在其自身中找到某个值时,它将一直沿作用域链向下(或向上延伸,具体取决于您对它的设想),并搜索该值以创建闭包。

翻译自: https://www.freecodecamp.org/news/closing-the-book-on-closures-50b095289bfa/

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

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

相关文章

java激励_激励干个人java的不足之处

1.你需要精通面向对象分析与设计(OOA/OOD)、涉及模式(GOF,J2EEDP)以及综合模式。你应该十分了解UML,尤其是class,object,interaction以及statediagrams。2.你需要学习JAVA语言的基础知识以及它的核心类库(collections,…

Bioconductor软件安装与升级

1 安装工具Bioc的软件包不能使用直接install.packages函数,它有自己的安装工具,使用下面的代码: source("https://bioconductor.org/biocLite.R")biocLite() 上面第二个语句将安装Bioconductor一些基础软件包,包括BiocI…

Laravel Kernel引导流程分析

Laravel Kernel引导流程分析 代码展示 protected function sendRequestThroughRouter($request) {# $this->app->instance(request, $request);# Facade::clearResolvedInstance(request);// 主要是这句代码$this->bootstrap();# return (new Pipeline($this->app)…

Android RecyclerView (一) 使用完全解析

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/45059587; 本文出自:【张鸿洋的博客】 概述 RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用。 据官方的…

数据透视表日期怎么选范围_透视范围

数据透视表日期怎么选范围by Tiffany White蒂芙尼怀特(Tiffany White) 透视范围 (Putting Scope in Perspective) In JavaScript, lexical scope deals with where your variables are defined, and how they will be accessible — or not accessible — to the rest of your…

feign调用多个服务_Spring Cloud 快速入门系列之feign–微服务之间的调用

我们将一个大的应用拆成多个小的服务之后,紧接着的一个问题就是,原本都在一个项目里,方法我可以随便调用,但是拆开后,原来的方法就没法直接调用了,这时候要怎么办?Spring Cloud提供了feign&…

Asix下日志包冲突

为什么80%的码农都做不了架构师?>>> Class org.apache.commons.logging.impl.SLF4JLogFactory does not implement org.apache.commons.logging. 最近集成asix包的时候发生如下错误,原因是程序运行时logFactoryImple加载了JBOSS下面的sff4j包…

kubernetes中mysql乱码_在kubernetes中部署tomcat与mysql集群-Go语言中文社区

在kubernetes中部署tomcat与mysql集群之前必须要有以下这些基础:1. 已安装、配置kubernetes2. 集群中有tomcat与mysql容器镜像3. 有docker基础具体步骤部署tomcat创建tomcat RC对象我们想要在kubernetes集群中配置tomcat服务器,首先要保证集群中的节点上…

c# 测试运行时间毫秒级

long currentMillis (DateTime.Now.Ticks - (new DateTime(1970, 1, 1, 0, 0, 0, 0)).Ticks) / 10000;/*代码*/long currentMillis1 (DateTime.Now.Ticks - (new DateTime(1970, 1, 1, 0, 0, 0, 0)).Ticks) / 10000;MessageBox.Show((currentMillis1 - currentMillis).ToStri…

nodejs_NodeJS历险记

nodejsby Elliott McNary埃利奥特麦克纳里(Elliott McNary) NodeJS历险记 (Adventures in NodeJS) I built an app a couple of weeks ago after going through FreeCodeCamp’s Front-End curriculum and wanted to write an update as I head into NodeJS-land. I was final…

pytdx 获取板块指数_能否增加一个通过股票代码,板块指数代码获得中文名称的接口?...

T0002/hq_cache/shex.tnfT0002/hq_cache/szex.tnf这个解码就是。/***************************************************股票代码列表和股票名称T0002/hq_cache/shex.tnfT0002/hq_cache/szex.tnf***************************************************/struct TdxSymbolMap {cha…

灵动标签调用友情链接

1、文字形式[e:loop{select * from [!db.pre!]enewslink where checked1 and classid1 order by myorder,20,24,0}] <li><a href"<?$bqr[lurl]?>" title"<?$bqr[lname]?>" target"_blank"><?$bqr[lname]?>&…

4-----Scrapy框架中选择器的用法

Scrapy提取数据有自己的一套机制&#xff0c;被称作选择器&#xff08;selectors&#xff09;,通过特定的Xpath或者CSS表达式来选择HTML文件的某个部分Xpath是专门在XML文件中选择节点的语言&#xff0c;也可以用在HTML上。CSS是一门将HTML文档样式化语言&#xff0c;选择器由它…

【原】Jenkins持续集成环境搭建之创建java项目的job【centos6.5 java maven git 项目】...

一、构建一个maven项目在jenkins主页上&#xff0c;左侧&#xff0c;选择“新建”&#xff0c;然后填写项目名称&#xff0c;选择“构建一个maven项目”二、Git配置保存之后&#xff0c;进入详细配置页面&#xff1a;这里的源码管理&#xff1a;选择git&#xff0c;输入代码的g…

linux修改java内存大小_Linux 和 windows修改java虚拟机内存大小

1、Java内存区域划分&#xff1a; 运行时的数据区:方法区和堆(各个线程共享的内存区域)&#xff0c;程序计数器、Java虚拟机栈和本地方法栈(线程私有的) 程序计数器&#xff1a;当前线程所执行字节码的行号指示器&#xff0c;字节码解释器就是通过改变计算器的值来选取下一条需…

html制作彩虹_制作彩虹

html制作彩虹by Gil Fewster吉尔弗斯特(Gil Fewster) 制作彩虹 (Making rainbows) This is a story about curiosity. It’s also about what happens when you stick a needle into your eye. If you happen to be eating a handful of grapes right this moment, maybe come…

python3 set_python3.x 基础三:set集合

| clear(...) 清空一个集合| Remove all elements from this set.>>>set1.clear()>>>set1set()| copy(...) 影子复制&#xff0c;指向同一个内存地址| Return a shallow copy of a set. |>>> list1[3, 2, 1, 1, 2, 3, 4, 5]>>>…

Linux内核分析作业第八周

进程的切换和系统的一般执行过程 一、进程调度的时机 中断处理过程&#xff08;包括时钟中断、I/O中断、系统调用和异常&#xff09;中&#xff0c;直接调用schedule()&#xff0c;或者返回用户态时根据need_resched标记调用schedule()&#xff1b; 内核线程可以直接调用sched…

iOS--数据存储NSUserDefaults

2019独角兽企业重金招聘Python工程师标准>>> 今天去面试&#xff0c;被问道NSUserDefaults的存取并手写出来&#xff0c;一时想不起来&#xff0c;回来之后看看之前的笔记&#xff0c;稍作一些整理 NSUserDefaults是一个单例&#xff0c;在整个程序中只有一个实例对…

巨人肩膀_如何站在巨人的肩膀上

巨人肩膀“If I have seen further than others, it is by standing on the shoulders of giants.” — Isaac Newton“如果我能比其他人看到更多&#xff0c;那就是站在巨人的肩膀上。” —艾萨克牛顿 In 1676, Isaac Newton spoke of the great thinkers who came before him…