手机版

从零开始轻松学习JavaScript闭包

时间:2021-09-06 来源:互联网 编辑:宝哥软件园 浏览:

本文为初学者,大神轻喷。

什么是结束?

不熟悉javascript的人会接触到一种叫做闭包的东西,听起来很高大上。网上有各种各样的解释。其实我个人觉得没有必要用太理论化的概念去看待闭包。

事实上,你每天都在使用闭包,但你就是不知道。

例如:

Var cheese=' cheesevar test=function(){ alert(cheese);}好的,你已经写好了结束语。

函数也是一种数据类型

变量cheese是全局范围内的变量。创建测试函数时,测试和奶酪共享一个全局范围。

你需要理解的另外一件事是,在js中,函数和变量本质上是一样的。函数也是一种数据类型。

从上面的定义也可以看出这一点。如果你不相信我,我们来看看。

alert(奶酪);警报(测试);

让我们看看有哪些类型的测试和奶酪:

警报(测试类型);

警报(奶酪类型);

看,只是类型不同。它们都是数据类型。

唯一的区别是函数类型的测试可以有自己的内部逻辑,而字符串类型的奶酪只能存储一个文字值,这就是区别,仅此而已。

乍看之下,唯一的区别是普通变量以相同的文字值存在,而函数需要放在括号中才能执行。

你看,我现在放一个括号:

test();

函数中的逻辑只有在括号被放置时才会被执行。

行动范围

让我们回到闭包,现在对前面的代码做一个小的更改:

Var cheese=' cheesevar test=function(){ alert(cheese);} function test 2(){ var cheese=null;test();} test2();那么,你认为现在的警报是零还是奶酪?

好好想想。

没错,还是奶酪。

就像我之前说的,函数测试和变量奶酪在同一个蓝天里——同一个范围。

函数测试和变量cheese共享的范围称为全局范围。就像地球一样,我们所有人都喜欢这个地球,可以在这里呼吸、吃饭和玩耍。

对于测试,他唯一能访问的范围是它自己的闭包和全局范围:

也就是说,在正常情况下,他无法访问其他闭包的内容,test2中定义的变量与此无关,所以弹出的奶酪仍然是全局范围内的奶酪。

函数可以创建自己的范围。

我们刚刚定义了一个测试函数,用{}包装的部分形成了一个新的作用域,叫做闭包。

事实上,在你对范围原则有了深刻的理解之后,闭包就被理解了。

就像地球是一个全球范围,你自己的房子是一个功能,你的房子是一个私人空间,也就是一个局部范围,也就是你自己建造了一个封闭!

你可以通过窗户看到外面的风景,比如院子里的一棵香蕉树,这样你就可以通过眼镜看到香蕉树的颜色、高度、树枝的粗细等等。

这个香蕉树相当于一个全局变量,您可以在自己的闭包中访问它的数据。

因此,在这个例子中,test是一个房子,其中可以通过窗口访问全局范围内的cheese ——变量cheese。

也就是说,奶酪在被测试访问时进入了封闭状态。

你觉得这个解释更容易理解吗?

现在,你能理解我开头说的,闭包实际上是我们每天都在使用的东西吗?

我们给出闭包的第一个注解:

1.闭包是创建函数时存在的私有作用域,可以访问所有父作用域。

回到刚才的例子:

Var cheese=' cheesevar test=function(){ alert(cheese);} function test 2(){ var cheese=null;test();}在这个例子中,test和test2都有一个作用域,对吗?他们不能互相拜访。例如,我在test中定义的变量不能被test2直接访问。

var test=function(){ var I=10;} function test 2(){ alert(I);} test2();这样,一旦test2函数被执行,编译就会失败,因为在test2的闭包中根本找不到变量I。首先,它会在自己的封闭中寻找我。如果找不到,就去父作用域。这里的父级是全局范围。可惜还是没有人。这就是所谓的范围链,一次查一级。如果找到顶层,仍然找不到,就会报错。

这里,需要注意的另一点是,如果在某个闭包中修改了全局作用域(或父作用域)中的一个变量,那么引用该变量的任何闭包都会受到牵连。

这确实是一个需要关注的地方。

例如

Var cheese=' cheesevar test=function(){ cheese=' cheese被偷了!'} function test 2(){ alert(cheese);} test();test 2();结果是:

很有趣,不是吗?

当我们定义一个函数时,就产生了闭包。如果此函数中有几个内部函数,则闭包与闭包嵌套在一起。

像这样:

function house(){ var footBall=' footBall ';/*客厅*/功能客厅(){var table='餐桌';Var沙发='沙发';alert(Football);}/*卧室*/功能卧室(){ var bed='大床';} living room();} house();功能屋是一个封闭体,其中定义了两个功能,即livingRoom客厅和卧室,每一个都形成了自己的封闭体。对他们来说,父母的范围就是房子。

如果我们想在livingRoom里面踢足球,执行LivingRoom功能的时候,它会先在自己的闭包里面找足球,如果找不到,它会在房子里面找。一个一个查,直到找到为止。当然,这个例子可能不太合适。但至少它展示了范围和闭包之间的联系。

同样,闭包是创建函数时存在的私有作用域,可以访问所有父作用域。因此,理论上,任何函数都是闭包!

2.如何公开私有数据

之前有这样一个例子

var test=function(){ var I=10;} function test 2(){ alert(I);} test2();函数test和test2各自形成一个闭包,这两个闭包不能访问彼此的私有数据。例如,在test2中不能直接访问test中定义的变量。

那么问题来了。当然,这一面与挖掘机无关。这里的问题是,test2有没有办法访问其他闭包中的私有变量?

当然有办法。最直接的想法是,我可以定义一个全局变量,在测试中将私有数据分配给全局变量,然后在测试2中访问它。

是的,因为两个函数共享一个全局范围,所以这个方法确实可行。我确实看到许多人在许多项目中这样做。

那么,有没有更好的方法呢?要知道,全局范围是一个敏感的地方,不小心就会出现变量名重复的问题。顺便说一下,在全局范围内,尽量不要使用热门变量,如temp、a、b和c。

因此,这涉及到返回值的知识,而你必须习惯C语言教材中这样的代码

int sum(int a,int b){ return a b;}int all=sum(3,5);这是一个简单的求和函数,很多人逐渐形成了这样的想法:函数的返回值是文字值,可以是数值型,也可以是布尔型,也可以是字符串。

在很多强类型语言中,比如Java、C、C,这是真的。然而,return在JavaScript中非常流行。

正如上一节所解释的,js的函数也是一种数据类型,你可以把它想象成int、float、double之类的东西。

那么,既然int可以用作函数的参数或返回值,那么函数也可以!

请看下面两句话:

在js中

如果一个函数作为参数传入,它被称为回调函数。

如果函数作为返回值返回,它将返回一个闭包。

本章不讨论回调函数。如果不知道回调函数是什么,可以阅读相关文章

或者上面的例子,我们希望测试中的变量可以在test2中访问,我们可以这样做:

var test=function(){ var I=10;/*定义一个函数来公开变量I */var get=function(){ return I;}返回get//暴露得到I }function test2()的函数{ var fn=test();//接收测试暴露的功能告警(fn());//在test }test2()中获取私有数据;

测试函数中的get方法是一个内部函数,它自己形成一个闭包。test是它的父范围,所以它可以得到I的值。

我进入get方法的闭包,被包起来,最后被返回。

对于test2,可以访问测试函数,因此可以调用并执行测试函数来获取其返回值。

你可能会说,我只是在考试中还我,何必呢。

是的,有道理。

但是,如果我想在测试中访问多个私有数据呢?

现在你可以看到了!

现在,我们给出关于闭包的第二个评论:

从应用程序的角度来看,闭包可以公开函数或对象的私有数据,而不会影响全局范围。

通过这张图更容易理解吗?我们将在本节中只讨论函数中的私有数据。

2.将私有数据打包到json对象中

这个例子只是说明在js中,返回可以是一个基本数据类型,也可以是一个函数类型。

其实JavaScript是一种基于对象的语言,它也有对象的概念,所以我们可以把你需要的东西包装成一个对象返回!

代码开启:

var test=function(){ var apple=' apple ';Var梨='梨';/*定义一个函数来公开水果*/varget水果={apple:apple,pear:pear}返回get水果;//公开得到I } function test 2(){ varget水果=test()}的函数;//接收测试暴露的函数console . log(get水果);} test2();像这样用{}括起来的是一个js对象,叫做json。你可能经常听到json这个词,它相当高。事实上,它只是包装在{}中的数据。

它是键值对的形式,这与Java中的HashMap非常相似。

在这个例子中,我们可以用一个{}直接包装要公开的私有数据,形成一个json对象并返回它。

因为是js对象,alert看不到里面的具体内容,所以我们使用console.log(),结果如下:

膨胀后:

这样可以吗?额外的原型是原型链,这将在后面讨论。

3.让我们做一个紫色的葫芦

大家还记得《西游记》中孙悟空耍弄遮天的紫金葫芦。只要你拿着这个葫芦,叫别人的名字,如果你答应了,别人就会被吸进去。

好吧,这个紫色的葫芦不就像一个封口吗?

正确所以,让我们用闭包的知识来做一件有趣的事情。

body div id=' box ' style=' width :50 px;高度:50 px;背景技术: # 333;color: # fff文本对齐:居中;线高:50px '小恶魔/div/尸体

紫金葫芦里面的源代码大概是这样的:

var紫色葫芦=function(id){ var DOM element=document . getelementbyid(id);var returnObject={ DOM element : DOM element,background color : function(color){ DOM element . style . background color=color;},点击:函数(fn){ domment . onclick=fn;} };return对象;}注:我用中文定义变量纯粹是为了方便。在实际开发中,千万不要使用中文变量。

我们向返回的对象添加了三样东西:

1.domElement

如果你传入一个id,我会用document.getElementById包装得到一个dom元素,最后的操作就是这个dom元素。也就是说:

Var box1=紫葫芦(' box ')。dome element;var box 2=document . getelementbyid(' box ');alert(box 1===box 2);粘贴图像. png

他们是一样的,一样的。

紫金葫芦('盒');

一旦执行了这一行代码,紫金葫芦就会返回returnObject对象,也就是说。我们喊了一声“盒子”,那个带着id盒子的小恶魔一答应就被放了进去,然后我们就可以用它做任何我们想做的事情了!

例如,将其更改为背景色:

2 .背景色向元素添加背景色的方法

Var box=紫葫芦(' box ');box.backgroundColor('红色');

3 .单击将click事件添加到元素中,您需要传入一个回调函数

Var box=紫葫芦(' box ');Box.click(function(){ alert '),没有人会吐槽这个无聊的作者。小恶魔有尊严,好吗?啊!');});结果:

也许你已经发现了,这些方法和jQuery有些相似吗?

以上就是本文的全部内容。希望本文的内容能给大家的学习或工作带来一些帮助,也希望多多支持我们!

版权声明:从零开始轻松学习JavaScript闭包是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。