闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
创建闭包的常见方式,就是在一个函数内部创建另一个函数。
在javascript语言中,闭包就是函数和该函数作用域的组合。
从这个概念上来讲,在js中,所有函数都是闭包
(函数都是对象并且函数都有和他们相关联的作用域链scope chain)。
用途:
- 读取函数内部的变量。
- 让这些变量的值始终保持在内存中。不会在调用后被自动清除。
- 方便调用上下文的局部变量。利于代码封装。
例:
var scope = "window scope";
function checkScope() {
var scope = "local scope";
function f() {
return this.scope;
}
return f;
}
checkScope()(); //=> "window scope"
闭包的this指向的是它定义的地方的this
非严格模式下,函数内部的this指向全局对象(严格模式下,this为undefined),
函数 checkScope 的this指向的是window对象,所以返回window scope
应用场景
1. 为节点循环绑定click事件
当前页面有5个button,要求是点击每个button的时候弹出对应的编号
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<button>Button0</button>
<button>Button1</button>
<button>Button2</button>
<button>Button3</button>
<button>Button4</button>
</body>
</html>
for(var i = 0;i<btnList.length;i++){
//错误 onclick是异步触发的,
btnList[i].onclick = function(){
console.log(i)
}
//正确的代码
//采用“立即执行函数Immediately-Invoked Function Expression (IIFE)”的方式创建作用域
(function(i){
btnList[i].onclick = function(){
console.log(i)
}
})(i);
}
立即执行函数不传 i
2. 延续局部变量的寿命
img对象经常用于数据上报:
var report = function(src) {
var img = new Image();
img.src = src;
}
report('http://xxx.com/getUserInfo');
这段代码在运行时丢失部分数据上报,原因是img是report函数中的局部变量,当report函数调用结束后,img对象随即被销毁,而此时可能还没来得及发出http请求,所以此次请求就会丢失。使用闭包把img对象封闭起来,就可以解决数据丢失的问题:
var report = (function() {
var imgs = [];
return function(src) {
var img = new Image();
imgs.push(img);
img.src = src;
}
})()
匿名函数
匿名函数就是没有名字的函数,有时候也称为《 拉姆达函数》。如下:
function a(a1, a2, a3) {
// 函数体
}
var a = function(a1, a2, a3) {
// 函数体
}
复制代码以上两个例子在逻辑上等价,其主要的区别是:
前者会在代码执行前被加载到作用域中,而后者则是在代码执行到那一行的时候才会有定义。
另一个重要的区别就是:
函数声明会给函数一个指定的名字,而函数表达式则是:创建一个匿名函数,然后将这个匿名函数赋给一个变量。
function(a1, a2, a3) {
// 函数体
}
这例子也是可以的,但是无法调用,因为没有指向这个函数的指针
但可以将这个函数作为参数传入另外一个函数,或者从一个函数中返回另一个函数时就可以使用这种形式来定义匿名函数。