目录
闭包是一个很神奇的东西,之前用的时候总是感觉懵懵懂懂不得其精髓,最近利用一些空闲时间研究了下闭包,现在将这段时间总结的一些案例和概念整理整理吧。
一、什么是闭包
闭包:在一个作用域中可以访问另一个作用域的变量或者函数
如下:
<script>
// 1
// 闭包:在一个作用域中可以访问另一个作用域的变量或者函数
// 未发生闭包
function fn(){
var n = 10;
return n
}
fn(); // 输出10
// 好处/特点:延展了函数的作用域范围
function fn(){
var n = 10;
return function (){
return n
}
}
var f = fn()
console.log(f()) // 输出10,通过访问父级作用域获得数据
</script>
二、演示闭包可以实现的效果
<script>
// 2
function getFun(n){
return function(m){
return n + m
}
}
// 求100 + m
var fn100 = getFun(100)
// 求1000 + m
var fn1000 = getFun(1000)
console.log(fn100(1)) // 输出 101
console.log(fn1000(1)) // 输出1001
</script>
三、闭包的案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<ul id="heroes">
<li>安其拉</li>
<li>礼拜</li>
<li>诸葛亮</li>
<li>狄仁杰</li>
</ul>
</body>
</html>
<script>
// 3
// 方式1:给li注册点击事件(对象的自定义属性)
var heroes = document.getElementById('heroes');
var list = heroes.children;
for(var i = 0; i < list.length; i++) {
var li = list[i];
li.index = i
li.onclick = function (){
// 点击li的时候输出当前li的索引
console.log(this.index)
}
}
// 方式2:使用闭包的方式
// 问题:延展了作用域但降低了性能
var heroes = document.getElementById('heroes');
var list = heroes.children;
for(var i = 0; i < list.length; i++) {
var li = list[i];
(function (i){
li.onclick = function (){
// 点击li的时候输出当前li的索引
console.log(i)
}
})(i)
}
</script>
四、定时器执行的过程
setTimeout的工作就是把第一个参数放到任务队列上来
当执行代码的进程已将执行栈上的代码全部执行完后才会通过消息循环 取出任务队列要执行的代码依次执行
五、通过使用闭包创建一个更灵活的函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
我是字体的演示
<button id="btn1" size="12">按钮1</button>
<button id="btn2" size="14">按钮2</button>
<button id="btn3" size="16">按钮3</button>
</body>
</html>
<script>
// 5案例
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn2');
var btn3 = document.getElementById('btn3');
btn1.onclick = function(){
document.body.style.fontSize = '12px';
}
btn2.onclick = function(){
document.body.style.fontSize = '14px';
}
btn3.onclick = function(){
document.body.style.fontSize = '16px';
}
// 闭包方式 创建一个更灵活的函数
function makeFun(size){
return function(){
document.body.style.fontSize = size + 'px';
}
}
btn1.onclick = makeFun(12)
btn2.onclick = makeFun(14)
btn3.onclick = makeFun(16)
// 拓展
function makeFun(size){
return function(){
document.body.style.fontSize = size + 'px';
}
}
var box = document.getElementById('box');
var buttons = box.children;
for(var i = 0; i<buttons.length;i++){
var btn = buttons[i];
// 获取标签自定义的属性
var size = btn.getAttribute('size')
btn.onclick = makeFun(size);
}
</script>
六、有效读取并区分当前是否存在闭包练习
<script>
// 6案例
var name = 'The Window';
var object = {
name:'My Object',
getNameFunc: function(){
console.log(this,'-p--p-p-p-p-p-p-p-pp-p-') // 此处this指向object对象
return function (){
console.log(this,'-----ooooo-----') // 此处this指向全局作用域Window
return this.name;
}
}
}
// 由于是在全局作用域下直接调用getNameFunc()()
console.log(object.getNameFunc()()); // 输出:The Window
// 此处和以上console同理
var fn = object.getNameFunc()
fn() // 此为全局作用域下调用
var name = 'The Window';
var object = {
name:'My Object',
getNameFunc: function(){
var that = this;
return function (){
// 此处that指向object对象
console.log(that,'-p--p-p-p-p-p-p-p-pp-p-')
return that.name;
}
}
}
console.log(object.getNameFunc()()); // 输出:My Object
</script>