当前位置:网站首页>闭包的常见用法
闭包的常见用法
2022-07-22 11:16:00 【快乐的蜜蜂】
作为js的三大核心之一,闭包是什么呢?闭包就是函数执行时依赖变量作用域,而这个作用域是在函数定义时决定的,而不是函数调用时决定的,简单来说,就是闭包这个特性,在外部函数可以访问到局部函数的作用域,好啦,话不多少,下面请看例子.
// 下面的这段代码 我相信你们能看懂
var name = "张三";
function getName () {
var name = "李四";
function f () {
return name;
}
return f();
}
getName (); // "李四"
// 接下来 这段代码呢 你就明白了 我上面为什么这么说了
var name = "张三";
function getName () {
var name = "李四";
function f () {
return name;
}
return f;
}
var user = getName ();
user(); // 这个结果是什么呢
// 什么 居然也是 "李四",不是 "张三", 没错上面 已经解释的很清楚了
闭包就是函数执行时依赖变量作用域,而这个作用域是在函数定义时决定的,而不是函数调用时决定的,所以返回的结果 还是 "李四"
有一点头绪之后 我们来看一下,下面这段程序吧
function funConst () {
var arr = [];
for (var i=0; i< 10; i++) {
arr[i] = function () {
return i;
}
}
return arr;
}
var aaa = funConst();
aaa[5](); // 结果是什么呢? 10
卧槽,居然是10,怎么回事,小老弟,这跟我们想要的结果完全不一样啊,发生了什么...
因为他们在同一个函数里面调用的,所以他们可以共享变量,当程序执行完了之后,i的值变成了10,所以说数组里面的所有值都是10
那这个怎么变成我们想要的呢
function funConst () {
var arr = [];
for (var i=0; i< 10; i++) {
arr[i] = function (num) {
return function () {
return num;
}
}(i)
}
return arr;
}
var aaa = funConst();
aaa[5](); // 那么这个结果是什么呢 5
哇,好神奇,结果变成了我们想要的样子了, 这个是什么原理呢,我们利用了闭包,把i作为一个变量传给了一个函数,那么函数里面的num就是他的局部变量了,然后把这个num返回回来,他们就有各自的作用域,而不会相互影响.
其实 还有一种实现方法,就是es6里面的let变量,它本身就是块级作用域
function funConst () {
let arr = [];
for (let i=0; i< 10; i++) {
arr[i] = function () {
return i;
}
}
return arr;
}
let aaa = funConst();
aaa[5](); // 结果也是 5
接下来 我们来看看 下一个例子,你就会更加的熟悉一些了
var name = "张三";
var obj = {
name: "李四",
getName: function () {
return function () {
return this.name;
}
}
};
obj.getName()(); // 这个结果是什么呢 => "张三"
为什么会是张三呢, 因为,每个函数被调用时,活动变量都会拿到 this 和 arguments ,内部函数在搜索这两个变量时,只会搜索到活动对象位置,因此永远也不可能直接访问到函数的这两个变量
那我们 非要拿到对量里面的李四怎么办呢,在函数外给他增加this,拿到当前this的作用域
var name = "张三";
var obj = {
name: "李四",
getName: function () {
var _this = this;
return function () {
return _this .name;
}
}
};
obj.getName()(); // 结果就是 李四啦
有些人可能会说,请看下面的代码
var name = "张三";
var obj = {
name: "李四",
getName: function () {
return this.name;
}
};
obj.getName(); // 结果也是 李四
这个是当然的呀,因为 在 obj中 this.name 本来就是 李四
当然我们也可以通过call 和 apply来改变函数的作用域
function name() {
return this.name
}
var obj = {
name: "张三"
};
name.call(obj); // 结果是 "张三"
我们的apply用法
var list = [1,5,3,2];
Math.max.apply(this, list) // apply的第二个参数是必须传入数组
使用闭包的好处,还有一个就是不污染 全局作用域, 例如 当我们做程序开发的时候,不同的人,难免会出现相同的定义,导致程序 出现一些不好维护的问题
function count (num) {
for (var i=0; i<num; i++) {
console.log(i);
}
console.log(i); // 计数 这里拿到的值是 5,很明显这被污染了
}
count(5);
我们 通过闭包的方式
function count (num) {
(
for (var i=0; i<num; i++) {
console.log(i);
}
)()
console.log(i); // 导致一个错误, 这样子 就不会影响我们下面的变量了
}
count(5);
我知道的闭包的大概用法就在这里了,如果有什么问题,欢迎指出.
边栏推荐
- Wechat applet comprehensive case practice 2
- Cjson source code reading notes
- pytorch, 指定显卡问题
- NVIDIA Clara data
- C# Winform开发 打开txt文件 并显示在 RichTextBox中 加上编辑后保存功能
- Wechat applet introduction tutorial learning notes - layout basis of UI chapter
- shell远程执行命令
- Process control - if statement
- 蓝桥杯-递增三元组
- Cartesi mars 2022 Review
猜你喜欢
Blue bridge cup-k-fold range
New cover of time: metauniverse will change everything
WinAppDriver 自动测试 winform 自动测试的部署
Significance learning record of FFT in MATLAB
Run pychar on the server. Prompt: already running
C# Winform开发 WinAppDriver 自动测试的使用
Application & rich text editor & file upload
使用go golang配置时 遇到的connect: connection refused问题
Learning notes of wechat applet introduction tutorial - operation feedback of UI chapter
C# 窗体应用DataGridView,使用数据库(Sql和MySQl)对DataGridView绑定数据源,获取数据
随机推荐
安全至上北京现代i-GMP平台厉害之处到底在哪?
Double pointer in linked list -- fast and slow pointer
C# Winform开发 打开txt文件 并显示在 RichTextBox中 加上编辑后保存功能
C# Winform开发 WinAppDriver 自动测试的使用
regular expression
Prompt "warning: remote host identification has changed" when SSH
隧道调频广播覆盖系统数字选频光纤拉远漏缆覆盖解决方案
Makefile中如何自动生成头文件依赖
9.用户权限相关命令
Bash variable -- position parameter variable
Character processing command
Servlet
Web编程入门 1.1登录功能的实现
9. User authority related commands
Binance 华语社区 x Cartesi AMA 回顾
8.SSH高级命令
Simple sentences -one
重新安装的nvidia显卡驱动
解决编译mosquitto时遇到的问题
FPN资料