概述
目录
- 1、什么是闭包,什么是作用域
- 1.1 变量作用域
- 1.2 闭包是啥?如何改变变量调用格局
- 1.3 闭包的特性
- 2、怎么用闭包,闭包实例应用
- 2.1 常见闭包实例
- 2.2 闭包异步函数的应用
- 2.3 柯里化的应用
- 3、闭包的优缺点
- 3.1 优点
- 3.2 缺点
- 4、片尾彩蛋
【写在前面】2023年确实想整理好一些前端的学习心得,另外也秉着不让后学习者少走弯路的原则,博主是日夜挑灯阅尽千篇才整理出来的,闭包一直是面试高频词汇,也是很多高级应用必不可缺的,下面务必给我三分钟,让我为您详细解答一下闭包的前世今生。希望能给您带来帮助。
涉及知识点:变量作用域;闭包;垃圾回收机制,;立即执行函数;闭包异步函数,柯里化
1、什么是闭包,什么是作用域
1.1 变量作用域
闭包理解的前提是我们应该先去理解变量作用域,正常也无外乎全局变量和局部变量;
全局变量能被所有的函数应用,局部变量的话只能在声明区域应用。
好比如下所示的函数:
var hdd = '黄大大';
function hddFunc(){
var kf = '黄小小';
console.log(hdd+'好帅');
}
function kongfu(){
console.log(kf+'好丑');
}
hddFunc(); //输出黄大大好帅
kongfu(); //输出报错,VM138:7 Uncaught ReferenceError kf is not defined
从上面的实例我们不难发现,全局变量谁都能动,局部变量只能在自己地盘使用。
1.2 闭包是啥?如何改变变量调用格局
要是我函数体内就要用外部的变量呢?也不是不可以,接下来看下面这个实例
var hdd = '黄大大';
function hddFunc(){
var kf = '黄小小';
console.log(hdd+'好帅');
function kongfu(){
console.log(kf+'好丑');
}
}
hddFunc(); //输出黄大大好帅
kongfu(); //输出报错,VM138:7 Uncaught ReferenceError kf is not defined
输出结果还是一样的。那么我将kongfu()调用放在hddFunc()体内呢?如下所示调整:
var hdd = '黄大大';
function hddFunc(){
var kf = '黄小小';
console.log(hdd+'好帅');
function kongfu(){
console.log(kf+'好丑');
}
kongfu();
}
hddFunc();
//输出黄大大好帅
//输出黄小小好丑
从这个实例不难发现只有在变量声明区内调用才有效,也确实是实现了kongfu()函数输出了非自身区域内变量的值。其实到这里我就讲完了闭包。
总之一句话:
闭包就是指内部函数有权访问到外层函数的作用域,能读取到外层函数作用域声明的变量,或者我们可以将变量kf和函数kongfu()之间的环境(桥梁)叫做闭包,特别要注意的是必须得在父函数内调用。
1.3 闭包的特性
从上面我们可以特别清楚的看的出来,首先是函数内声明函数,其次是函数内部调用外部参数,再者就是回收机制。
其实在上面的函数调用过程中hddFunc函数体内声明的变量kf因为有kongfu()函数的使用,所以永远不会销毁,正常函数体内的局部变量会随着函数执行完成后而销毁。因此在这里我总结一下闭包三大特性:
- 函数嵌套函数;
- 函数内部可调用外层函数声明的变量和参数;
- 闭包机制下的参数和变量是不会被垃圾回收机制回收(销毁);
2、怎么用闭包,闭包实例应用
2.1 常见闭包实例
function hdd() {
var sq = 1
function haoshuai() {
return ++sq
}
return haoshuai
}
var hddhs = hdd();
console.log(hddhs());
//输出 2
function hdd() {
var sq = 1
function haoshuai() {
return ++sq
}
return haoshuai
}
var hddhs = hdd();
hddhs();
console.log(hddhs());
//输出3
小记:从这里不难发现帅气值变量sq始终都是在的,调用一次就会存储一次加一,从这里就可以确定sq这个变量一直没有被回收。
2.2 闭包异步函数的应用
先用实例和大家介绍一下:
for (var i = 1; i < 5; i++) {
setTimeout(function () {
console.log(i+"-黄大大好帅");
}, 50);
}
//输出:
5-黄大大好帅
5-黄大大好帅
5-黄大大好帅
5-黄大大好帅
但是我就是想让他在遍历里面按照正常顺序来输出。这个时候我们可以用到闭包的概念。我们创建了一个立即执行函数,将变量i放在立即执行函数内,其实也就相当于这里的i被setTimeout异步函数给引用了,从而实现i变量叠加后会保存原有的值。也验证了一点特性,函数嵌套函数的说法
for (var i = 1; i < 5; i++) {
(function(i){
setTimeout(function () {
console.log(i+"-黄大大好帅");
}, 50);
})(i)
}
//输出:
1-黄大大好帅
2-黄大大好帅
3-黄大大好帅
4-黄大大好帅
其实最推崇的应该是下面这个方式,将变量i用let进行声明,因为let所声明的变量只在let命令所在的代码块内有效。如下所示:
for (let i = 1; i < 5; i++) {
setTimeout(function () {
console.log(i+"、黄大大好帅");
}, 50);
}
//输出:
1-黄大大好帅
2-黄大大好帅
3-黄大大好帅
4-黄大大好帅
2.3 柯里化的应用
柯里化是函数的一种高阶技术,我们可以理解为函数的一种转换,如下:
//求和函数
function sum(a, b,c) { return a + b+c; }
//柯里化辅助函数curry()
//curry函数的实现(不知道多少入参,所以用了递归)
function curry(fn,arr=[]){
let len = fn.length; //函数的长度是函数形参的个数
return function (...args){
let arrs = [...arr,...args];
if(arrs.length < len){
return curry.call(this,fn,arrs);
}else{
return fn(...arrs);
}
}}
let getSum = curry(sum);
console.log(getSum(1,2,3)) //輸出6
console.log(getSum(1)(2,3)) //輸出6
console.log(getSum(1)(2)(3)) //輸出6
我们不难发现里面函数嵌套函数,且应用函数体外的变量。
3、闭包的优缺点
3.1 优点
1.能读取函数外层的变量,从而避免全局变量被污染
2.外层变量会一直存在内存中,函数结束后不会被回收机制回收
3.2 缺点
1.正因为不被回收机制,所以会导致内存消耗过大,伸直引发溢出,所以慎用哦!
4、片尾彩蛋
如果觉得这篇文章对您有帮助的话,想支持博主的可以上皇榜看看哟,皇榜点击此处进入
最后
以上就是喜悦身影为你收集整理的【面试之闭包】前端面试那些事(2)三分钟深入理解闭包(附详解实例)1、什么是闭包,什么是作用域2、怎么用闭包,闭包实例应用3、闭包的优缺点4、片尾彩蛋的全部内容,希望文章能够帮你解决【面试之闭包】前端面试那些事(2)三分钟深入理解闭包(附详解实例)1、什么是闭包,什么是作用域2、怎么用闭包,闭包实例应用3、闭包的优缺点4、片尾彩蛋所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复