闭包的个人理解

闭包

什么是闭包?

闭包是一个函数和声明该函数的词法环境的组合,这个词法环境包含了嵌套函数所能访问的所有局部变量,嵌套的函数可以访问其外部环境中的变量。
通常情况下,闭包的形式如下:

function parentFunc(){
    //变量声明
    ......
	return	function childFunc(){
		......
	}
}

内部函数使用外部函数的变量时,它会保留这些变量的引用,即使外部函数已经执行完毕,变量依然可以访问。

var createCounter = function(n) {
    var previous = n;
    
    return function() {
    	//执行顺序:1) return previous; 2) previous++;
        return previous++; 
    };
};

/** 
 * const counter = createCounter(10)
 * counter() // 10
 * counter() // 11
 * counter() // 12
 */

闭包的使用

相同算法不同参数

例如如果要计算公司内部组长、下属的薪酬,用的是同一种算法,但是每种员工的工资基数不同:

function wages(x){
   return function bonus(y){
   	return x+y;
   }
}
var leader=wages(20000)(2000);  //22000
var staff=wages(10000)(1000);  //11000
模拟私有方法

使用闭包模拟私有方法,对于一些方法不想公开时可以使用闭包:
暂时还不太懂用法

循环事件赋值回调

将HTML元素循环遍历,并定义每一个的点击事件,很容易就会写成下面的样子:

function showHelp(help) {
 document.getElementById('help').innerHTML = help;
}

function setEvent(){
     var helpText = [
     {'id': 'email', 'help': 'Your e-mail address'},
     {'id': 'name', 'help': 'Your full name'},
     {'id': 'age', 'help': 'Your age (you must be over 16)'}
   ];
   for(var i=0,len=helpText.length;i<len;i++){
   	var item=helpText[i] //var 或 let 都一样是helpText[2]
   	document.getElementById(helpText[i].id).onfocus=function(){showHelp(item.help)}
   }
}
setEvent()

运行的结果是每一个HTML的onfocus事件触发时都显示 ‘Your age (you must be over 16)’。
这是因为上面的 setEvent 方法中,var声明的 i 作用域为function setEvent,var没有块级作用域,因此在触发onfocus事件时i==2此时就输出helpText[2]。
那么,如何才能实现呢?有三种方法:

  • 将 i 的声明改成let ,因为let (有块级作用域)声明时 i 的作用域是在for{}每一次循环的代码块中,因此在触发onfocus时 每一次 item 都是随着 i 重新定义,所以onfocus事件中的 i 是当前代码块中的 i 。
  • 再使用一次闭包:
 function showHelp(help) {
 document.getElementById('help').innerHTML = help;
}

function secondClosure(help){
   return function(){
   	return showHelp(help) 
   }
}

function setEvent(){
     var helpText = [
     {'id': 'email', 'help': 'Your e-mail address'},
     {'id': 'name', 'help': 'Your full name'},
     {'id': 'age', 'help': 'Your age (you must be over 16)'}
   ];
   for(var i=0,len=helpText.length;i<len;i++){
   	var item=helpText[i]  
   	//调用secondClosure,参数help指向每次循环时的helpText[i].help,调用时就会正确传入help
   	document.getElementById(helpText[i].id).onfocus=secondClosure(helpText[i].help)
   }
}

或者使用立即执行函数:

 function setEvent(){
	  var helpText = [
      {'id': 'email', 'help': 'Your e-mail address'},
      {'id': 'name', 'help': 'Your full name'},
      {'id': 'age', 'help': 'Your age (you must be over 16)'}
    ];
	for(var i=0,len=helpText.length;i<len;i++){
		(function(){
			var item=helpText[i]
			document.getElementById(helpText[i].id).onfocus=
			function(){showHelp(helpText[i].help)}
		})()
	}
}

闭包的坏处

在特殊情况下使用闭包,但是一般不建议用闭包,因为这样的方式是将方法定义在对象或类的构造器上,每次创建对象时方法会被重新创建,这对内存损耗,处理速度上很不利。可以将方法添加至对象或类的原型上:

function A(name,age){
	this.money=1000
	this.name=name
	this.age=age
}

A.prototype.getMoney=function(){
	return this.money
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值