一,理解闭包就要先理解作用域
作用域scope 在js中作用域scope是由函数划分的,所有属于全局作用域的变量都是window对象的属性(prototype);
function A(){
var num =2;
function B(){
console.log(num);
}
}
//B函数可以访问A函数,A函数外不能访问A函数里定义的变量,那么B函数能访问A函数里定义的变量;
//那么可以将B函数作为返回值,然后提供给外部(作为接口),那么外部就能访问A函数里的变量了
//链式作用域chain scope :子对象一级一级向父级对象寻找变量
var num = 2;
var obj = {
num :3,
getNum :function (){
console.log(this.num)
}
}
obj.getNum();//3
var n = 2;
var obj = {
n:3,
getNum:function (){
setTimeout(console.log(this.n),3000);
}
}
obj.getNum();//3
var n = 2;
var obj = {
n:3,
getNum:funciton(){
setTimeout(function(){
console.log(this.n)
},3000)
}
};
obj.getNum();//2
二,闭包closure:内层的函数可以引用他外层函数内的变量,即使外层的执行已经终止
//闭包的典型案例,实现访问函数内部的变量
function people() {
var name = "maoguotao";
function getname(){
console.log(name);
}
return getname;
}
var person = people();
person();
函数getName就是这个people函数的对外接口提供能够访问到内部定义的name,因此getName函数和变量name组成的环境就称之为闭包;
闭包的两个特点:1,可以访问函数内部的变量,2,这些变量的值始终是保存在内存中
1.可以访问函数内部的变量
function A(){
var name = "maoguotao";
this.getName = function () {
console.log(name);
}
}
var a = new A();
a.getName();
2.这些变量的值始终是保存在内存中
function A(){
var name = "maoguotao";
addName = function (){
name = name + "12";
}
function getName(){
console.log(name+"34");
}
return getName;
}
var a = A();
a();
//maoguotao34
addName();
a();
//maoguotao1234
a函数执行了两次,也就是说闭包getName函数执行了两次,实际上局部变量name是保存在内存中的,并没有在第一次的a()调用完之后清除,因为A函数是getName闭包函数的父函数,而getName函数被赋给a全局变量,使得getName函数始终在内存中,而getName函数依赖于A函数,所以A函数也是在内存中,不会在调用结束后清除;
闭包的缺点:
1,闭包使得函数中的变量保存在内存中,对内存消耗很大,不能滥用,会造成网页的性能问题,在IE中可能导致内存的泄露,解决办法就是在退出函数之前将使用的局部变量全部删除;
2,闭包会在父函数外部,改变父函数的内部变量的值,因此,把父函数当作Object对象使用,把闭包当作他的公用方法,把内部变量当作他的私有属性;