闭包概念->闭包作用->立即执行函数->for in例子如果每次输出不同的值( 闭包,定时器第二个变量,promise/let)->在jquery中的使用
由于javascript中特有的作用域,函数中的局部变量不能够被外部获得或使用,而函数内部可以使用外部的全局变量,并且javascript的垃圾回收机制会在function执行过后自动销毁函数内部的变量。
这就是我们就需要运用闭包来解决这个问题,在我看来闭包的主要作用是:
1.使得函数内部的变量能够安全的被外部获取
2.使得函数在执行后,内部变量依旧被保存在内存中,不会被自动销毁(使用后要用null销毁,否则会占用内存)
3.可以将函数内部的变量私有化
三个经典场景:
1.通过循环给每一个dom节点绑定事件,用闭包把循环所需的i封装起来
2.封装变量
3.延长局部变量寿命
function foo(){
var a = 0;
function bar(){
return a++;
}
return bar;
}
var Fooo = foo();
如上面的代码所示,当Fooo在外部调用了foo()之后,bar()被保存了下来,由于bar()内部调用了父级作用域里的变量a,所以父级function在函数结束后foo()不会被自动销毁,从而形成了闭包。
总的来说闭包就是创建了内部变量,不能被外部随意的修改,但是能够通过特定的接口来获取。一般来说闭包会和立即执行函数配合使用,因为立即执行函数能够对函数实现封装,从而达到避免污染全局变量的目的。立即执行函数可以在函数前用!+ - =等符号来实现,但是建议使用双括号包裹来实现,从而实现块级结构,再多人开发中不会互相影响。jquery中的封装便是使用了闭包和立即执行函数的思想(Immediately Invoked Function Expression).
举例说明:
如果我们要实现,从0到4每一秒输出一个数字的效果:
for(var i=0; i<5; i++){
setTimeOut(function(){
console.log(i);
},1000)
)
如果我们用这种方法来实现的话,输出结果将是5->5,5,5,5,5。第一个5是由于for语句的执行顺序,而其他几个数字是由于公共变量i一直在被修改,当1000ms后输出的时候其实i都是5。要解决这一问题,我们有五种解决方法: 1.闭包 2.setTimeOut自带参数 3.用let实现块级作用域 4.用es6中的promise 5.es6中async wait
闭包:
for(var i=0; i<5; i++){
(function(j){
setTimeOut(function(){
console.log(j);
},1000);
})(i);
}
setTimeOut:
for(var i=0; i<5; i++){
setTimeOut(function(pram){
console.log(pram);
},1000,i)
}
let:
for(let i=0; i<5; i++){
setTimeOut(function(){
console.log(i);
},1000)
)
es6中的let语句所声明的i是局部变量,只在本轮循环内有用,每一轮都是一个新的变量i,所以互相之间不影响。
THIS指向问题
函数调用(指向window) 对象方法(对象) 构造函数(实例化出来的对象) 计时器调用(全局) 匿名函数(window)
原型中的this指向调用他的对象不指向本身