1.能够访问另一个函数作用域的变量的函数
闭包就是一个函数,这个函数能够访问其他的函数的作用域中的变量
2.闭包函数是在widow作用域下执行的也就是说,this是指向widows
3.闭包在读取函数内部变量时,会让这些变量始终保存在内存中,不会自动清除
使用场景
因为作用域问题一个函数内的变量,外部是访问不到的所以才会出现闭包函数
优点,用途
1.在内存中维持一个变量,不会被浏览器清除
2.读取函数内部的变量
3.方便调用上下文的局部变量。利于代码封装。
缺点
1.闭包会使函数内的变量都被保存在内存中,内存消耗很大,降低网页的性能,所以不能滥用闭包
解决方法是,在退出函数之前,将不使用的局部变量全部删除
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script>
// 为什么会有闭包,因为作用域的问题
// 自调用()(),
function a(){
return function b(){
// 一个函数里面放回一个函数这种情况称为闭包
console.log('这是访问闭包里的返回函数');
}
}
// 访问闭包的方法
a()();
// 闭包的用途,保存私有的方法和私有的数据
// 优点:浏览器默认会清理掉没有使用的变量,可以通过闭包的方式内部调用变量来实现储存的变量和方法
// 缺点:但是相应的会造成浏览器内存的占用,使得内容运行缓慢
function b(){
var b = 2;
return function c(){
var sum = b + 1;
console.log(sum);
}
}
b()();
// ()() 还有个用途就是生成一个 命名空间, 可以 类似于自调用,前面的括号放我们的闭包函数
// 后面的括号相当于调用这个闭包函数里面也可以传参数
// 事件队列:在大量事件待执行的时候会把事件列一个队列等待调用
var dom = document.querySelectorAll('li');
for(let j=0;j<dom.length;j++){
dom[j].onclick=function(){
console.log(j+1)
}
}
// 需求:根据点击打印出点击的下标
// let 是局部变量,而var 是全局变量,因此后者需要调用闭包来达到需求
for(var i =0;i<dom.length;i++){
dom[i].onclick=(
function(a){
return function(){
console.log(a+1)
}
}
)(i)
}
// 倘若不进行闭包处理,var的变量会执行完for循环,点击时i全变成了6
// 添加事件的扩展
// DOM 事件 最常用的
var lis = document.querySelectorAll('li')
for(let i=0;i<lis.length;i++){
// 参数;事件类型 事件处理函数(回调) 监听器 冒泡或者捕获(布尔值)
lis[i].addEventListener('click',function(){
console.log(i);
},false)
}
// 和onclick的区别,onclick会覆盖,也就是说只能同一个节点有一个
// 而addEventListener不会覆盖
// 伪数组 arguments 不能直接使用数组方法
// 但是可以通过call 和 apply 上下文方法来使用
Array.prototype.join.call('arguments',['-']);
// 在arguments数组里的属性之间加一个 -
</script>
</body>
网友评论