用户:
爱探险的可乐呀查看:6 回复:13 评论:6 创建时间:2021-02-16T19:47:03

哎嘿大家好啊ヾ(≧▽≦*)o
我是可乐~~~
今天咱们来一期JavaScript进阶教程——闭包
(不会吧不会吧不会有人说闭包是基础吧)
好的废话不多说直接开始教程——
-----------------------------------------------------------------------------------------------
1.js的变量作用域
要想理解闭包这个东东,就要先理解JavaScript的变量作用域
js中的变量分为两种:
全局变量和局部变量
js中规定,函数中可以直接读取全局变量
举个栗子🌰:
var a = 999; //定义一个全局变量
function yiGeHanShu() { //定义一个函数,函数名可以随便起,毕竟这只是个例子()
console.log(a); //输出全局变量a
}
yiGeHanShu(); //运行结果:999
另外呢
在函数外部无法读取函数内的局部变量
再举个栗子🌰:
function yiGeHanShu() {
var a = 999;
}
console.log(a); //运行结果:报错
这就是JavaScript特有的“链式作用域”,
在这一个作用域下面的作用域能读取这个作用域的变量 但是这个作用域不能读取下一个作用域的变量()
有亿点绕口是不是 这段需要慢慢琢磨哦()
那怎么从外部读取局部变量呢?
闭包就出来了——
-----------------------------------------------------------------------------------------------
2.简单闭包的定义和使用
由于各种各样的原因
我们要读取一个函数的内部变量
但是 正常情况下,我们是做不到哒
所以 有请闭包上场()
再再举个栗子🌰:
function a() {
var a = 999;
function b() {
console.log(a);
}
}
这样定义函数的话,函数b()就在函数a()内部
这个时候
函数a()这个作用域的所有局部变量,对函数b()这个下面的作用域都是可读取的
既然b()可读取a()的局部变量,那把b()作为a()的返回值不就行了吗?!
function a() {
var a = 999;
function b() {
console.log(a);
}
return b;
}
var c = a(); //这时c是a()的返回值,也就是一个函数,我们在接下来调用它
c(); //运行结果:999
一个简单的闭包就完成辽~
或者 还有一种写法
function a() {
lan_de_xie
return b;
}
a()();
a()()又是什么东东呢?
前面的a()表示函数调用,返回b这个函数
然后把前面的a()看成一个整体,再调用一次(这时调用的是b()这个函数)
运行结果就是999~
上个例子中,b()这个函数就是闭包
那闭包的概念是什么呢?
欢迎在评论区打出你的答案()
我的理解是:
闭包函数就是能够读取函数内部变量的函数
因此可以简单理解为:
函数里的函数()
好家伙()这不就是套娃嘛()
-----------------------------------------------------------------------------------------------
3.闭包的用途
闭包这东东有个好处
就是函数中的变量都会保留在内存中
那我们不就可以做一个计数器吗?
开整!
普通思路
如果我们不用闭包,用普通的思路,那么代码将会是这样的
var counter = 0;
function add() {
counter++;
}
add();
add();
add();
//此时counter为3
诶这个时候你就有可能会说了
“可乐这效果可以啊 为啥要用闭包啊”
那你想一想 你可以手动控制counter作弊啊是不是
lan_de_xie
add();
counter += 27346198746526516734;
//此时counter为27346198746526516735
那怎么防止这种作(dong)弊(shou)行为呢?
这就需要用到闭包了
闭包思路
function add() {
var counter = 0;
return function () {
return ++counter;
}
}
var a = add();
a();
a();
a();
//此处counter为3
为什么是++counter呢?
这就要涉及到我们刚学js就知道的a++和++a的区别()
a++:运算过程中先执行a表达式,之后再执行自增运算。
++a:运算过程中先执行自减运算,之后再运行a表达式。
度娘拿过来参考的,大家看一下就可以了
如果用counter++,那运行结果就是3
那为什么不用add()()呢?
因为用add()()的话每次函数就会重新运行一遍 也就是counter会清零
所以用变量储存add()的值
然后再调用add()函数返回的函数
上面这段话还是得好好琢磨()
-----------------------------------------------------------------------------------------------
4.思考题()
如果你能理解下面两段代码的运行结果,应该算理解闭包的运行机制了吧()
tips:代码来自阮一峰老师的博客
1.
//此段代码为前端 请勿用node运行~
var n = "我是窗口";
var obj = {
name: "我是对象",
getName: () => {
return () => {
return this.name;
};
},
}
alert(obj.getName()());
2.
//此段代码为前端 请勿用node运行~
var n = "我是窗口";
var obj = {
name: "我是对象",
getName: () => {
var that = this;
return () => {
return that.name;
};
},
}
alert(obj.getName()());
好了这就是这期教程的全部内容了
我是可乐
我们下期再见~(~ ̄▽ ̄)~
BSS梅者如西补充个东西:
就是本文第1、2段代码所用的变量/函数的命名方法:
(小)驼峰命名法,通常用于单词过多或者中文设置变量。
首先比如说:Football Club Barcelona改成变量就是footballClubBarcelona;
再比如说:巴萨改成变量就是baSa。
具体用法就是把单词/音节连一起把音节的首字母大写,再把新变量名的首字母变小写
另外还有一个跟(小)驼峰命名法相似的就是下划线命名法。
举个同样的例子:Football Club Barcelona改成变量就是Football_Club_Barcelona;
巴萨改成变量就是Ba_Sa。
具体用法是把单词/音节的中间隔一个_。
以上两个用法都用于普通变量,其他类型的变量还有其他用法。
(求置顶)
点赞0
评论
爱探险的可乐呀才发现有点部分打错了
第三部分
++a:运算过程中先执行自加运算,之后再运行a表达式。
是自加,粘贴忘记改了()
-----------------------------------------------------------------
如果用counter++,那运行结果就是2
因为第一个a()的返回值为0
-----------------------------------------------------------------
思考题
1.
//此段代码为前端 请勿用node运行~
var name = "我是窗口";
var obj = {
name: "我是对象",
getName: () => {
return () => {
return this.name;
};
},
}
alert(obj.getName()());
2.
//此段代码为前端 请勿用node运行~
var name = "我是窗口";
var obj = {
name: "我是对象",
getName: () => {
var that = this;
return () => {
return that.name;
};
},
}
alert(obj.getName()());
思考题涉及到了一个很重要的知识点:this关键字
点赞0
评论