一,理解闭包就先要理解作用域
作用域scope 在js中作用域scope是由函数划分的,所有属于全局作用域的变量都是window对象的属性(property);
//隐式的声明全局变量
function test(){
foo = "test";
}
function A() {
var num = 2;
function B(){
console.log(num);
}
}
//B函数可以访问A函数,A函数不能访问A函数里定义的变量,那么B函数能访问A函数里定义的变量。
//那么可以将B函数作为返回值,然后提供给外部(作为接口),那么外部就可以访问A函数里的变量了.
//链式作用域chain scope:子对象一级一级向父级对象寻找变量
二,闭包 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 delayAlert(msg,time){
setTimeout(function(){
alert(msg);
},time);
}
delayAlert("welcome",2000);
//用闭包实现函数curry化
//数字求和函数的函数生成器
function addGenerator( num ){
//返回一个简单的函数.求两个数字的和,其中一个来自函数生成器
return function (toAdd){
return num + toAdd;
}
};
var addFive =addGenerator(5);
alert(addFive(4) == 9);
//构造函数里的this指的是构造函数的实例对象
function A(){
var name = "maoguotao";
this.getName = function(){
console.log(name);
}
}
var a = new A();
a.getName();
//构造函数里的this指的是构造函数的实例对象
function B(){
var name = "MGT360124";
this.getName = function (){
console.log(name);
}
}
var b = new B();
b.getName();
2,这些变量的值始终是保存在内存中
function A(){
var name = "maoguotao";
addName = function (){
name = name+"12";
}
function getName(){
console.log(name+"34");
}
return getName;
}
var a = A();
a();
addName();
a();
a函数执行了两次,也就是闭包getName函数执行了两次,实际上局部变量name是保存在内存中的,并没有在第一次的a()调用完之后清除,因为A函数是getName闭包函数的父函数,而getName函数被赋给a全局变量,使得getName函数始终在内存中,而getName函数依赖于A函数,所以A函数也是在内存中,不会在调用结束后清除。
闭包的缺点:
1,闭包使得函数中的变量保存在内存中,对内存消耗很大,不能滥用.会造成网页的性能问题,在IE中可能导致内存的泄露,解决办法就是在退出函数之前将不使用的局部变量全部删除
2,闭包会在父函数外部,改变父函数的内部变量的值.因此,把父函数当作object对象使用,把闭包当作他的公用方法(public Method);把内部变量当作他的私有属性(private value)
热门评论
错误,
A函数声明未执行,
addName也就未声明,
你去调用肯定undefined