js中闭包

何为闭包

在一个函数内可以访问到另一个函数(外层作用域)的局部变量时,此时「函数」和「函数内部能访问到的变量」的总和,就是一个闭包。
在这里插入图片描述

看得到的闭包?

 (function(){
	var local='局部变量';
	 function foo(){
		 console.log(local);
		 console.dir(foo);
	 }
	 foo()
 })()

在这里插入图片描述

闭包的作用

闭包常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」。还有一个作用就是,让这些变量的值始终保持在内存中。

有一些变量不希望直接被其他人调用,则可以通过函数,让别人可以「间接访问」。如果设为全局变量,全部用户都可以访问,被人不小心改了,谁知道会引发什么后果呢?

闭包经典使用:嵌套函数+尾调用

让全局作用域访问到局部作用域的变量。

function outer(){
	var local='局部变量'
	return function (){
		console.log(local);
	}
}
let foo =outer();
foo();

local 变量和 匿名函数就组成了一个闭包(Closure)。

模拟执行上下文栈

👉JS执行过程与执行上下文(栈)
在这里插入图片描述
按理来说,outer函数执行完成后,里面的变量对象都会被销毁,但是因为生成了闭包。outer函数执行上下文对象中的变量对象不会立刻被销毁,需要等到闭包内部变量被调用完成才会被销毁。

主要是因为匿名函数的执行上下文对象中的scope属性保存了对outer变量对象的引用。

看下该匿名函数执行上下文对象:

anonymousContext={
	VO:{
		arguments:
			length:0
	},
	Scope:[AO,outerContext.VO,globalContext.AO],
	this:undefined
}

如果在函数A的内部调用函数B,那么在A的调用帧上方,还会形成一个B的调用帧。等到B运行结束,将结果返回到A,B的调用帧才会消失。

尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。

一定要函数套函数吗

因为需要局部变量,所以才把 local 放在一个函数里,如果不把 local 放在一个函数里,local 就是一个全局变量了,达不到使用闭包的目的——隐藏变量。

函数套函数只是为了造出一个局部变量,跟闭包无关。

闭包应用

定义具有特定功能的js模块(隐藏变量接口)

设计私有的方法和变量。(作用)

function myModule() {
	//私有数据
	var msg = 'Smyhvae Haha'
	//操作私有数据的函数
	function doSomething() {
		console.log('doSomething() ' + msg.toUpperCase()); //字符串大写
	}

	function doOtherthing() {
		console.log('doOtherthing() ' + msg.toLowerCase()) //字符串小写
	}
	//通过【对象字面量】的形式进行包裹,向外暴露多个函数
	return {
		doSomething1: doSomething,
		doOtherthing2: doOtherthing
	}
}
let m=myModule();
m.doSomething1();
让变量的值始终保持在内存中

存储变量(作用)

  function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }

  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000

注意:nAdd是全局变量

模仿块级作用域

if(){}for(){}等没有作用域,所以在其块内声明的变量,在外部是可以使用的。(匿名自执行函数)

//javaScript没有块级作用域的概念
function fn(num){
    for(var i=0;i<num;i++){}
    console.log(i);//在for外部i不会失败
}
fn(2);

if(true){
    var a=13;
}
console.log(a);//在if定义的变量在外部可以访问

通过匿名自执行函数可以模拟块级作用域

 (function(){
        //i在外部就不认识啦
        for(var i=0;i<count;i++){}
  })();
  console.log(i);//报错,无法访问
其他:内存泄漏问题

变量不可销毁,需要主动销毁

function assignHandler() {
    var element = document.getElementById('someElement');
    var id = element.id;
    element.onclick = function() {
        alert(id);
    };
    element = null;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值