首页 新闻 会员 周边 捐助

如何理解javascript里的闭包?

0
悬赏园豆:30 [已解决问题] 解决于 2014-02-24 12:45

我属于菜鸟,刚学会javascript 会做一些效果。不太明白js里的闭包的概念。谁呢告诉我闭包是什么,该怎么理解?如果是百度就算了,最好是说一些大白话,基础有限。很多专业术语不明白。

我真不会起的主页 我真不会起 | 初学一级 | 园豆:151
提问于:2013-03-13 16:56
< >
分享
最佳答案
0
在Javascript中闭包(Closure)

一、什么是闭包?

“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。看下面这段代码:
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();
这段代码有两个特点:
1、函数b嵌套在函数a内部;
2、函数a返回函数b。
这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

二、另一个例子

模拟私有变量
functionCounter(start){
var count = start;
return{
increment:function(){
count++;
},
get:function(){
return count;
}
}
}
var foo =Counter(4);
foo.increment();
foo.get();// 5
这里,Counter 函数返回两个闭包,函数 increment 和函数 get。 这两个函数都维持着 对外部作用域 Counter 的引用,因此总可以访问此作用域内定义的变量 count.
收获园豆:10
cssfirefly | 菜鸟二级 |园豆:212 | 2013-03-13 17:04
其他回答(4)
0

我认为下面这篇文章是讲解闭包通俗易懂的

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

收获园豆:10
陈希章 | 园豆:2538 (老鸟四级) | 2013-03-13 18:16
0

说闭包前,你要知道两件事情:(也许你已经知道了)

1.js中函数也是对象,因此可以当做参数,也可以当做返回值:如

function test(){

    var fun = function(){alert("hello");};

    return fun;

}

var f = test();

f();

 

2.你要知道,变量的作用域。

var count = 0;

function add(a,b){

count ++;

var sum = a+b;

return sum;

}

var c = add(1,2);

c=add(2,3);

alert(count);

(1)函数外面是没法访问sum的,函数内部是可以访问其外部的count

(2)add每一次执行后 内部 a b 变量是销毁的

现在说闭包,举个例子:

function add(a){

    var sum = function(b){

           return a+b;

    };

    return sum;

}

var add5 = add(5);

var add100 = add(100);

var s = add5(6);

s=add5(20);

s=add100(300);

s=add100(152);

 

你会发现,sum函数引用了外部变量 a ,add函数执行以后,本应销毁 a 的,但是由于sum的引用,它会留在内存中。

sum函数对外部变量a的引用就产生了闭包。

 

初略解释作用域链原理(不确切(因为术语太多),但是就是那么一回事):

1.定义函数的时候,函数会有一个属性,记录它所处的作用域。

2.函数执行的时候,如果内部没有找到某个变量,就会通过上面所述的属性,在定义它所处的作用域里找。

 

再解释一遍上面的例子

var count = 0;

function add(a,b){

count ++;

var sum = a+b;

return sum;

}

var c = add(1,2);

c=add(2,3);

alert(count);

函数add之所以可以访问到count,是因为add定义的时候,add会有一个属性指向当前作用域window,add内部没有 count,会通过window找到。

 

 

var count = 0;

function add(a){

    var sum = function(b){

    count++;

           return a+b;

    };

    return sum;

}

var add5 = add(5);

var s = add5(6);

add定义的时候 add 有个属性指向了window,add 内部可以通过此属性访问window中定义的变量[count]

add执行的时候,每执行一次回申明一个sum函数,sum会有个属性记录当前所处作用域,这个作用域记录了add中所有的变量[a],并且有一个指针指向add所处的作用域[count]。

add5(6)执行的时候,b在sum函数内部;内部找不到a,就会在函数add中找;内部找不到count,先在add中找,再在window找。

 

闭包就是这么产生的 :add执行过后本来a应该销毁的,但是由于 sum中还有个属性间接地可以访问a 。

第二次执行add,a是存在另一个地方的,和第一次执行的并不影响。

 

至于闭包的应用实践不赘述。

收获园豆:10
acjialiren | 园豆:191 (初学一级) | 2013-03-14 11:18
0

闭包就是一个“对象”,里面有函数生成的时候的上下文的变量的引用

KallMeNeo | 园豆:247 (菜鸟二级) | 2013-03-16 11:27
0

最讨厌老外造词了,搞得人家一头雾水。其实闭包这东西说白了就是,如果一个对象在外部有它的引用存在,它这个对象就不会被垃圾回收而已。

少年学编程 | 园豆:3 (初学一级) | 2013-04-12 17:20
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册