从零开始轻松学习JavaScript闭包
本文为初学者,大神轻喷。
什么是结束?
不熟悉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或者邮箱删除。