一. 什么是闭包
高级程序设计三中: 闭包是指有权访问另外一个函数作用域中的变量的函数. 可以理解为 ( 能够读取其他函数内部变量的函数)
闭包的作用: 正常函数执行完毕后, 里面声明的变量被垃圾回收处理掉, 但是闭包可以让作用域里的 变量, 在函数执行完之后依旧保持没有被垃圾回收处理掉
闭包最⼤的作⽤就是隐藏变量
可以实现私有变量、特权变量、储存变量等
function Person ( ) {
var name = 'cxk' ;
this . getName = function ( ) {
return name;
}
this . setName = function ( value ) {
name = value;
}
}
const cxk = new Person ( )
console. log ( cxk. getName ( ) )
cxk. setName ( 'jntm' )
console. log ( cxk. getName ( ) )
console. log ( name)
函数体内的 var name = 'cxk' 只有 getName 和 setName 两个函数可以访问,外部⽆法访问,相对于将变量私有化。
二、闭包的实例
function foo ( ) {
var name = "kebi" ;
return function ( ) {
console. log ( name) ;
} ;
}
var bar = foo ( ) ;
bar ( ) ;
接下来通过一个实例来感受一下闭包的作用:
接下来实现一个计数器大家肯定会觉得这不是很简单吗
var count = 0 ;
function add ( ) {
count = count + 1 ;
console. log ( count) ;
}
add ( ) ;
var count1 = 0 ;
function add1 ( ) {
count1 = count1 + 1 ;
console. log ( count1) ;
}
add1 ( ) ;
当我们需要更多地时候, 这样明显是不现实的, 这里我们就需要用到闭包.
function addCount ( ) {
var conut = 0 ;
return function ( ) {
count = count + 1 ;
console. log ( count) ;
} ;
}
这里解释一下上边的过程:
addCount ( ) 执行的时候, 返回一个函数,
函数是可以创建自己的作用域的,
但是此时返回的这个函数内部需要引用 addCount ( ) 作用域下的变量 count,
因此这个 count 是不能被销毁的. 接下来需要几个计数器我们就定义几个变量就可以,
并且他们都不会互相影响, 每个函数作用域中还会保存 count 变量不被销毁, 进行不断的累加
常见面试题
for ( var i = 0 ; i < 4 ; i++ ) {
setTimeout ( function ( ) {
console. log ( i) ;
} , 300 ) ;
}
原因: js 执行的时候首先会先执行主线程, 异步相关的会存到异步队列里,
当主线程执行完毕开始执行异步队列, 主线程执行完毕后,
此时 i 的值为 4 ,
说以在执行异步队列的时候, 打印出来的都是 4 ( 这里需要大家对 event loop 有所了解 ( js 的事件循环机制) )
如何修改使其正常打印: ( 使用闭包使其正常打印)
for ( var i = 0 ; i < 4 ; i++ ) {
setTimeout (
( function ( i ) {
return function ( ) {
console. log ( i) ;
} ;
} ) ( i) ,
300
) ;
}
for ( var i = 0 ; i < 4 ; i++ ) {
setTimeout (
( function ( ) {
var temp = i;
return function ( ) {
console. log ( temp) ;
} ;
} ) ( ) ,
300
) ;
}
for ( var i = 0 ; i < 4 ; i++ ) {
( function ( i ) {
setTimeout ( function ( ) {
console. log ( i) ;
} , 300 ) ;
} ) ( i) ;
}
JavaScript 实现每次调用一个函数自动加1
var getId = ( function ( ) {
var i = 0 ;
return function ( ) {
return ++ i;
} ;
} ) ( ) ;
console. log ( getId ( ) ) ;
console. log ( getId ( ) ) ;
真实的获取多个元素并添加点击事件
var op = document. querySelectorAll ( "p" ) ;
for ( var j = 0 ; j < op. length; j++ ) {
op[ j] . onclick = function ( ) {
alert ( j) ;
} ;
}
for ( var j = 0 ; j < op. length; j++ ) {
( function ( j ) {
op[ j] . onclick = function ( ) {
alert ( j) ;
} ;
} ) ( j) ;
}
for ( var j = 0 ; j < op. length; j++ ) {
op[ j] . onclick = ( function ( j ) {
return function ( ) {
alert ( j) ;
} ;
} ) ( j) ;
}
for ( var j = 0 ; j < op. length; j++ ) {
op[ j] . onclick = ( function ( ) {
var temp = j;
return function ( ) {
alert ( j) ;
} ;
} ) ( ) ;
}
3. 闭包的缺陷:
通过上边的例子也发现, 闭包会导致内存占用过高, 因为变量都没有释放内存