函数执行造成一个私有做用域,保护里面的私有变量不受外界的干扰,这种保护机制叫作闭包。闭包
一个简单的闭包:函数
var utils = (function(){
return {
}
})()
复制代码
在团队开发过程当中,咱们一般会把本身的代码存放在一个私有做用域中,若是别人须要使用某些方法的话,能够经过return或者window.xxx暴露在全局下。this
jQuery源码也是利用这种保护机制的spa
~function(){
var jQuery = function(){
}
window.$=window.jQuery=jQuery
}()
复制代码
闭包解决选项卡问题3d
<div class="tabBox" id="tabBox">
<ul>
<li>标题1</li>
<li>标题2</li>
<li>标题3</li>
</ul>
<div class="selected">content1</div>
<div>content2</div>
<div>content3</div>
</div>
var tabBox = document.getElementById('tabBox'),
oList = tabBox.getElementsByTagName('li'),
oDivList = tabBox.getElementsByTagName('div');
function changeTab(index){
//index 存储当前点击li的索引
for(var i=0;i<oList.length;i++){
oList[i].className = oDivList[i].className = null //清除样式
}
oList[i].className = oDivList[i].className = 'selected'
}
for(var i=0;i<oList.length;i++){
oList[i].onclick = function(){
//三次循环给三个li都绑定了一个方法,可是都没有执行,当循环结束了,i此时为3,
//等到点击的时候,就没法实现想要的效果了
changeTab(index)
}
}
复制代码
解决办法是:code
自定义属性方式(能够给当前元素加一个属性)cdn
for(var i=0;i<oList.length;i++){
oList[i].myIndex = i;
oList[i].onclick = function(){
changeTab(this.myIndex)
}
}
复制代码
闭包机制blog
for(var i=0;i<oList.length;i++){
oList[i].onclick = (function(i){
//执行自执行函数首先会造成一个私有做用域
//接下来 形参赋值 i=0,i=1,i=2
return function(){
changeTab(i)
}
})(i)
}
//造成不销毁的私有做用域,不必定要有return,咱们也能够写成这样
for(var i=0;i<oList.length;i++){
(function(i){
oList[i].onclick = function(){
//oList[i].onclick占用了返回的function,因此这个做用域也不会被销毁
changeTab(i)
}
})(i)
}
复制代码
如今有这样一道题索引
function fn(){
var i=1;
return function(n){
console.log(n + i++)
}
}
var f= fn()
f(10) // 11
fn()(10) //11
f(20) //22
fn()(20) //21
复制代码
首先咱们考虑变量提高内存
function fn(){ //fn内部会造成一个私有做用域,在私有做用域内,会发生形参赋值和变量提高,在这里并无形参传递,咱们只考虑变量提高
var i=1;
return function(n){ //return 引用类型的值才会让私有做用域不销毁
console.log(n + i++) // 先把i=1赋值给结果,而后i本身再加1
}
}
var f;
f= fn() //把fn执行的返回结果赋值给f 实际上f是function(n){console.log(n + i++)}
f(10) //把fn执行的返回结果再执行,而且给它传递一个参数10
fn()(10)
f(20)
fn()(20)
复制代码
var num = 1,
obj = {
num:2,
fn:(function(num){
this.num*=2;
num+=2;
return function(){
this.num*=3;
num++;
console.log(num)
}
})(num)
}
var fn = obj.fn;
fn();
obj.fn();
console.log(num,obj.num)
复制代码