javascript 闭包 this闭包是什么?有好的论坛链接直接发过来也行

JavaScript闭包 懂不懂由你反正我是懂了
字体:[ ] 类型:转载 时间:
如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了
越来越觉得国内没有教书育人的氛围,为了弄懂JS的闭包,我使出了我英语四级吃奶的劲去google上搜寻着有关闭包的解释,当我看到stackoverflow上这一篇解答,我脑中就出现了一句话:就是这货没跑了! 不才译文见下,见笑了。 Peter Mortensen问: 就像老Albert所说的,“如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂。”好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了。 你们会怎么把它解释给一个充满好奇心的六岁孩子听呢? 注:我看过StackOverflow上给出的示例,但根本没用。 Ali的回答: 当function里嵌套function时,内部的function可以访问外部function里的变量。
代码如下: function foo(x) { var tmp = 3; function bar(y) { alert(x + y + (++tmp)); } bar(10); } foo(2)
不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp。 但,这还不是闭包。当你return的是内部function时,就是一个闭包。内部function会close-over外部function的变量直到内部function结束。
代码如下: function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); } } var bar = foo(2); // bar 现在是一个闭包 bar(10);
上面的脚本最终也会alert 16,因为虽然bar不直接处于foo的内部作用域,但bar还是能访问x和tmp。 但是,由于tmp仍存在与bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1. (考虑到六岁这个限制:我们其实可以建立不止一个闭包方法,比如return它们的数组,也可以把它们设置为全局变量。它们全都指向相同的x和相同的tmp,而不是各自有一份副本。) 注:现在来整点儿七岁的内容。 上面的x是一个字面值(值传递),和JS里其他的字面值一样,当调用foo时,实参x的值被复制了一份,复制的那一份作为了foo的参数x。 那么问题来了,JS里处理object时是用到引用传递的,那么,你调用foo时传递一个object,foo函数return的闭包也会引用最初那个object!
代码如下: function foo(x) { var tmp = 3; return function (y) { alert(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; alert(x.memb); } } var age = new Number(2); var bar = foo(age); // bar 现在是一个引用了age的闭包 bar(10);
不出我们意料,每次运行bar(10),x.memb都会自加1。但需要注意的是x每次都指向同一个object变量——age,运行两次bar(10)后,age.memb会变成2. 这和HTML对象的内存泄漏有关,呃,不过貌似超出了答题的范围。 JohnMerlino 对Ali说: 这里有一个不用return关键字的闭包例子:
代码如下: function closureExample(obj, text, timedelay) { setTimeout(function() { document.getElementById(objID).innerHTML = }, timedelay); } closureExample(‘myDiv', ‘Closure is created', 500);
深夜1:37 John Pick这样回答: JS里的function能访问它们的: 1. 参数 2. 局部变量或函数 3. 外部变量(环境变量?),包括 3.1 全局变量,包括DOM 3.2 外部函数的变量或函数。 如果一个函数访问了它的外部变量,那么它就是一个闭包。 注意,外部函数不是必需的。通过访问外部变量,一个闭包可以维持(keep alive)这些变量。在内部函数和外部函数的例子中,外部函数可以创建局部变量,并且最终退出;但是,如果任何一个或多个内部函数在它退出后却没有退出,那么内部函数就维持了外部函数的局部数据。 一个典型的例子就是全局变量的使用。 mykhal这样回答: Wikipedia对闭包的定义是这样的: In computer science, a closure is a function together with a referencing environment for the nonlocal names (free variables) of that function. 从技术上来讲,在JS中,每个function都是闭包,因为它总是能访问在它外部定义的数据。 Since scope-defining construction in Javascript is a function, not a code block like in many other languages, what we usually mean by closure in Javascript is a fuction working with nonlocal variables defined in already executed surrounding function. 闭包经常用于创建含有隐藏数据的函数(但并不总是这样)。
代码如下: var db = (function() { // 创建一个隐藏的object, 这个object持有一些数据 // 从外部是不能访问这个object的 var data = {}; // 创建一个函数, 这个函数提供一些访问data的数据的方法 return function(key, val) { if (val === undefined) { return data[key] } // get else { return data[key] = val } // set } // 我们可以调用这个匿名方法 // 返回这个内部函数,它是一个闭包 })(); db('x'); // 返回 undefined db('x', 1); // 设置data['x']为1 db('x'); // 返回 1 // 我们不可能访问data这个object本身 // 但是我们可以设置它的成员
看了这么多外国大牛的解答,不知道你懂还是不懂,反正我是懂了。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具彻底弄懂js循环中的闭包问题
(仅支持单关键字)
彻底弄懂js循环中的闭包问题
〖 作者:wenber 〗〖 发布日期: 〗
&&&第一次接触这个问题还是在我刚开始学js的时候,当时就是一头雾水,时隔一年多了,突然又想起了这个问题,在这个春气盎然的周末,我就坐下来研究下并把结果和大家分享下;
先看代码:
&!DOCTYPE HTML&
&&&&meta charset=&gbk&/&
&&&&title&闭包循环问题&/title&
&&&&style type=&text/css&&
&&&&&p {background:}
&&&&/style&
&&&p id=&p0&&段落0&/p&
&&&p id=&p1&&段落1&/p&
&&&p id=&p2&&段落2&/p&
&&&p id=&p3&&段落3&/p&
&&&p id=&p4&&段落4&/p&
&script type=&text/javascript&&
&for( var i=0; i&5; i++ ) {
&&&document.getElementById(&p&+i).onclick=function() {
&&&&&alert(i);
//访问了父函数的变量i, 闭包
&&每次循环就为对应的编号段落上添加一个click事件,事件的回调函数是执行一个alert();如果你以前没这么用过的话,估计也会认为单击某个段落就会弹出这个段落相应的编号0,1,2,3,4。但实际上是都是弹出5;
网上已经有很多讨论的博客了,他们给出了很多方法去实现弹出对应的编号。比较易于理解的方法如下:
1,将变量i保存在对应的段落的某个属性上:
var pAry = document.getElementsByTagName("p");
for( var i=0; i< 5; i++ ) {
pAry[i].no =
pAry[i].onclick = function() {
alert(this.no);
2,加一层闭包,i 以函数参数形式传递给内层函数:
~function test() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i< pAry. i++ ) {
(function(arg){
pAry[i].onclick = function() {
alert(arg);
})(i);//调用时参数
当然还有其他一些方法,但是都不太好理解。
而我要探索的是,为什么demo.html中的返回值始终是5。网上的说法是“变量i是以指针或者变量地址方式保存在函数中”,因为只有按照这样理解,才能解释。可是仅仅凭借一个结论怎么才能服众了?
&&&谈到指针或者变量地址这个话题,在C语言中倒是家常便饭了,但是在js这么性感的语言中,除了对象的及其对象属性的引用之外很少用到。一个基本的数据类型居然和指针拉上关系了,这勾起了探索的欲望。
3,试试下面的代码
~function test() {
var temp =10;
for( var i=0; i< 5; i++ ) {
document.getElementById("p"+i).onclick=function() {
alert(temp); //访问了父函数的变量temp, 闭包
&&它的执行结果是每个段落的弹出都是20,而不是10。说明当我们在单击的那个时候,temp的值已经是20。这是个似乎不需要我来说明,很显然的结果,因为在我们单击之前,temp已经被赋值为20了。
4,再看看下面的代码&&
我们在temp被改变值之前有程序去触发单击事件,弹出的是10;
~function test() {
var temp =10;
for( var i=0; i< 5; i++ ) {
document.getElementById("p"+i).onclick=function() {
alert(temp); //访问了父函数的变量i, 闭包
if(i===1){
var evt = document.createEvent("MouseEvents");
evt.initEvent("click",true,true);
document.getElementById("p1").dispatchEvent(evt);
&&这说明我们在p1上绑定的单击事件回调函数本来是要返回10的,当我再次手动去单击p0段落时,弹出20的原因是因为temp的值改变了。也就说明,每次弹出时,访问到的是temp此刻的值,而不是绑定时候的值;这可以说明变量temp确实是以变量地址保存的。扩展开去就是:函数内部访问了与函数同级的变量,那么该变量是常驻内存的。访问该变量实质上是访问的是变量的地址;
&&&通过以上的结论,那么我们可以简单的描述闭包的本质了:在子作用域中保存了一份在父级作用域取得的变量,这些变量不会随父级作用域的销毁而销毁,因为他们已经常驻内存了!
这句话也就说明了闭包的特性了:
1:因为常驻内存所以会造成内存泄露
2,只要其他作用域能取到子作用域的访问接口,那么其他作用域就有方法访问该子作用域父级作用域的变量了。
看这样一典型的闭包的例子:
function A(){
&&&var a=1;
&&&function B(){
C=A();//C取得A的子作用域B的访问接口
&console.log(C());//1
C能访问到B的父级作用域中的变量a
以上若有不足之处,欢迎指正,共同进步!
来源:/wenber/p/3632428.html
JavaScript探索者
Copyright@

我要回帖

更多关于 javascript闭包的作用 的文章

 

随机推荐