闭包是什么干啥的 我就不细讲了 随便搜很多,我就一句话说下:
一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
目录
具体的表现形式 就是一个函数尾部有return 输出一个函数,利用这个输出函数把当前函数的局部变量带出来,
如下所示:
function test1() {
var age = 19; // 局部变量
return function () {
console.log(age);
}
}
var func = test1();
// console.log(func);
func();
闭包到底有哪些作用,网上搜了一大片,很多面试宝典也写了很多,比如什么,可以读取函数内部的变量、让这些变量的值始终保存在内存中。有点无语,我要知道它的作用,我实际开发中会有哪些使用场景,下面是我的总结:
闭包的参数传递
最简单的例子如下
function test1(x) {
return function (y) {
//alert(x + y);
console.log(x);
console.log(y);
}
}
test1(10)(9);
以下例子更贴近地气
实现两张图片,点击第一张向左移动一定距离,点击第二张向右移动一定距离。
以下代码注释掉的是没有使用闭包的写法
<body>
<img id="l" src="images/left.png" alt=""><br>
<img id="r" src="images/right.png" alt="">
<script>
/*var left = 0, right = 0, speed = 50;//常规写法
var lImg = document.getElementById("l");
var rImg = document.getElementById("r");
lImg.onmousedown = function () {
left -= speed;
this.style.marginLeft = left + "px";
};
rImg.onmousedown = function () {
right += speed;
this.style.marginLeft = right + "px";
};
*/
function move(speed) {
var num = 0;
return function () {
//this 指的是当前标签对象
num += speed;
this.style.marginLeft = num + 'px';
console.log(this);
}
}
var lImg = document.getElementById("l");
var rImg = document.getElementById("r");
lImg.onmousedown = move(-50);
rImg.onmousedown = move(50);
</script>
</body>
总结:巧妙使用this,闭包中的this在外部调用move()时指代的是当前标签
rImg.onmousedown = move(50);其实就是代指以下代码
rImg.onmousedown = function () { right += 50; this.style.marginLeft = right + "px"; };
是不是很酸爽
函数节流中使用
以下实例主要是检测浏览器大小变化,使用节流可以减少cpu开销
注释部分是常规用法
<script>
/*var timer = null;//没有闭包的使用
window.onresize = function () {
clearTimeout(timer);
timer = setTimeout(function () {
console.log(document.documentElement.clientWidth);
}, 400);
}*/
function throttle(fn, delay) {
var timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(fn, delay);
}
}
//每次onresize变动,闭包可以保证函数重新执行
//勉强解释
window.onresize = throttle( ()=>
console.log(document.documentElement.clientWidth)
</script>
比较
两种方法都是利用了setTimeout,不同的是第二种方法加入的函数延迟执行时间,这个在第一种方案中很容易也具有此功能,加一个参数的事儿。
但第一种方案把tId设为函数的一个变量保存,而第二种创建了一个闭包来存储。个人觉得差距不大,很喜欢第一种,简单,高效。
但是第二种省内存,可扩展性高,
以下比较详细说明节流和闭包节流
https://www.cnblogs.com/dolphinX/p/3403821.html
作用域
如下的()();结构就是封闭作用域
(function () {
})();
Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收,否则这个对象一直会保存在内存中
封闭作用域又称为封闭空间,还有一个昵称为小闭包以及匿名函数自调。(为什么也是闭包个人理解是,内部变量可以丢出来让外部可以使用,符合闭包的定义:可以读取函数内部的变量),
主要作用是全局变量私有化
- 不污染全局空间
- 内部所有的临时变量执行完毕都会释放不占用内存。
- 可以保存全局数据
- 更新复杂变量
最简单的使用如下
var age=5;
(function () {
var age = 18;
console.log(age);
})();
(function () {
console.log(age);
})();
作用域链
<body>
<button id="btn">点我</button>
<script type="text/html">
var num = 3;
(function () {
(function () {
(function () {
var num = 2;
age.log(age);
(function () {
var age = 18;
console.log(num);
})();
})();
})();
})();
</script>
<script>
(function () {
var btn = document.getElementById("btn");
var btn1 = document.getElementById("btn");
var btn2 = document.getElementById("btn");
var btn3 = document.getElementById("btn");
var btn4 = document.getElementById("btn");
btn.onclick = function () {
alert(0);
}
})();
(function () {
var d = document;
var btn = d.getElementById("btn");
var btn1 = d.getElementById("btn");
var btn2 = d.getElementById("btn");
var btn3 = d.getElementById("btn");
var btn4 = d.getElementById("btn");
})();
(function (document) {
var btn = document.getElementById("btn");
var btn1 = document.getElementById("btn");
var btn2 = document.getElementById("btn");
var btn3 = document.getElementById("btn");
var btn4 = document.getElementById("btn");
})(document);
/*var num = 0;
for(var k in window){
num++;
document.write(k + "," + num + "<br/>")
}*/
</script>
</body>
高级排他中使用
以下为在事件中,多个相同元素的事件监测,一般使用如以下注释,两个for循环,也是很费力的
用闭包如何呢?
<body>
<ul>
<li class="current"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
/*var allLis = document.getElementsByTagName("li");
for (var i = 0; i < allLis.length; i++) {
allLis[i].onmouseover = function () {
for(var j=0; j<allLis.length; j++){
allLis[j].className = "";
}
this.className = "current";
}
}*/
var allLis = document.getElementsByTagName("li");
var lastOne = 0;
for (var i = 0; i < allLis.length; i++) {
(function (index) {
allLis[index].onmouseover = function () {
// 清除
allLis[lastOne].className = "";
// 设置
this.className = "current";
// 赋值
lastOne = index;
}
})(i);
}
</script>
</body>