javascript闭包概念及用法梳理

广告位招租
扫码页面底部二维码联系

今天在面试的时候被问到闭包,脑海中只知道【版权所有,侵权必究】【原创不易,请尊重版权】闭包就是函数里面的函数,但是答的时候就想本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。到了它的特性,就去说局部变量巴拉巴拉,全【版权所有,侵权必究】【转载请注明来源】局变量巴拉巴拉,回来想了一下,感觉自己还本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】是对闭包理解不够深入,所以遇到面试提问的原创内容,盗版必究。【原创内容,转载请注明出处】时候,一时间也无法表达出来。所以本文就来【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net梳理一下和闭包相关的概念及用法。

【原创不易,请尊重版权】【原创内容,转载请注明出处】【原创不易,请尊重版权】

函数内部的函数:私有函数【关注微信公众号:wwwtangshuangnet】

本文作者:唐霜,转载请注明出处。原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。

首先,我们从这个内部函数去说开,因为这个【版权所有,侵权必究】未经授权,禁止复制转载。是形式上的,如果一开始讲作用域,有点故意【转载请注明来源】【版权所有】唐霜 www.tangshuang.net。闭包在形式上就是函数内部的函数,比如:

未经授权,禁止复制转载。【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。
function add(a) {
  return function(b) {
    return a + b;
  }
}

var c = add(5)(10);

这是一个很奇怪的用法,第一次看到有fun未经授权,禁止复制转载。【作者:唐霜】ction()()这样的用法?请阅读这篇文章未经授权,禁止复制转载。。当执行add(5)的时候,返回的结果其本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。实是一个函数,而再执行这个函数,需要再传转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】入一个参数,所以就有了add(5)(10原创内容,盗版必究。本文作者:唐霜,转载请注明出处。)这样的用法。当然,这是一个极端的例子,【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。出现的太早,我们来看下最常见的一种用法吧著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。

【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】原创内容,盗版必究。本文作者:唐霜,转载请注明出处。
jQuery(function($){
  function message(msg) {
    alert(msg);
  }
  if($(window).width() > 1000) message('window宽度大于1000');
});

如果你用jquery,这段代码应该经常使【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】用吧。如果你仔细去观察,就会发现,第一个原创内容,盗版必究。【原创不易,请尊重版权】function被作为参数,传给了jQu本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】ery()这个函数,而在function转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net内,又有一个message()函数。所有【原创内容,转载请注明出处】原创内容,盗版必究。的jQuery代码被放在第一个funct【未经授权禁止转载】【版权所有,侵权必究】ion中去处理。第二个函数就是函数体内部本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net的函数,这个函数在函数体内声明,一旦外层【转载请注明来源】【转载请注明来源】函数执行完毕,那么这个函数就失去了作用,【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net在jQuery()外无法使用messag【版权所有,侵权必究】原创内容,盗版必究。e(),因此,message()是第一个【原创内容,转载请注明出处】【未经授权禁止转载】函数内部的私有函数。

【原创内容,转载请注明出处】【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。

变量的作用域【版权所有】唐霜 www.tangshuang.net

【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】

函数内部的变量有两种,一种是局部变量,一原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。种是全局变量。局部变量只在当前函数体内有【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net效,出了函数体,就回到全局变量的范围,局【作者:唐霜】【本文受版权保护】部变量无效。

【版权所有】唐霜 www.tangshuang.net【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】
var age = 10;function a(age) {
  return age + 1;
}
function b(_age) {
  return age + _age;
}
function c(_age) {
  var age = 11;
  function add() {
    return age + _age;
  }
  return add();
}

alert(a(9)); // 10 : 9 + 1
alert(b(2)); // 12 : 10 + 2
alert(c(5)); // 16 : 11 + 5

在上面的代码中,我们看b和c函数。b函数未经授权,禁止复制转载。【未经授权禁止转载】中的age直接引用了全局变量age(10【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】),而c函数中重新声明了局部变量age,转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net因此,全局变量age在c函数中无效。

【转载请注明来源】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。

但是在c中,函数内部有一个函数add()【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。,它的函数体内的age是指c中声明的局部【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】变量,而非全局变量age。从这个例子里,本文作者:唐霜,转载请注明出处。【转载请注明来源】反映出了变量的作用域,函数内的函数体里,【版权所有,侵权必究】【版权所有,侵权必究】如果没有声明局部变量,就会承认其父级甚至未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。祖先级函数的变量,以及全局变量。

【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】

闭包著作权归作者所有,禁止商业用途转载。

【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net【版权所有,侵权必究】

怎么样才算是一个闭包呢?我们来看下面的代【本文首发于唐霜的博客】【转载请注明来源】码:

原创内容,盗版必究。转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【作者:唐霜】
function a() {
  var age = 10;
  return function() {
    return age;
  }
}

var age = a();
alert(age()); // 10

按照我们前面说的作用域,在上面这段代码中转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】age是a()的局部变量,按道理,出了函本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。数,就不能被访问了。但是,a()返回了一【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net个私有函数,个这个函数返回了age,这导转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。致我们可以在a()外部,仍然可以访问到本原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net来是局部变量的age,这个时候,我们就把【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。这个内部函数称为闭包。它的原理就是,函数著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。内部的函数,可以访问父函数的局部变量。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。【版权所有,侵权必究】【原创内容,转载请注明出处】【本文受版权保护】

综合上面的阐述,我们要这样去理解闭包:未经授权,禁止复制转载。

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】未经授权,禁止复制转载。
  • 闭包是一个函数,它使用了自己之外的变量转载请注明出处:www.tangshuang.net原创内容,盗版必究。
  • 【本文首发于唐霜的博客】【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。
  • 闭包是一个作用域著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】
  • 【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。【本文受版权保护】【原创内容,转载请注明出处】
  • 闭包是“【版权所有】唐霜 www.tangshuang.net由函数和与其相关的引用环境组合而成的实体”。【版权所有】唐霜 www.tangshuang.net
  • 【作者:唐霜】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】
  • 严格的讲,闭包常常表现为一个函数内部的函【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。数,它使用了非自己定义的、自己所在作用域【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。内的变量,并且使这些变量突破了作用域的限【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。制。
  • 著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net【本文受版权保护】本文作者:唐霜,转载请注明出处。

所以,我们文章最开头的那段代码,也有一个【作者:唐霜】【作者:唐霜】闭包。

本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。原创内容,盗版必究。

一个典型的闭包:著作权归作者所有,禁止商业用途转载。

未经授权,禁止复制转载。【转载请注明来源】未经授权,禁止复制转载。
  • 函数内的函数转载请注明出处:www.tangshuang.net
  • 【本文受版权保护】【转载请注明来源】【原创内容,转载请注明出处】【原创内容,转载请注明出处】
  • 这个内部函数引用了父函数的局部变量本文作者:唐霜,转载请注明出处。
  • 【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net
  • 这个内部函数使引用的变量突破了作用域限制
  • 【未经授权禁止转载】【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net
var a = 1;
function fun() {
  return a + 1;
}
alert(fun());

这也可以算作一个闭包,a()引用了它之外【未经授权禁止转载】本文作者:唐霜,转载请注明出处。定义的变量。但是这不算严格的闭包,因为它【原创不易,请尊重版权】【作者:唐霜】没有在突破作用域的这个点上表现出来。

【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】原创内容,盗版必究。
var a = 1;
function fun() {
  var b = 2;
  return function() {
    return a + ++b;
  };
}
var c = fun();
alert(c()); // 4
alert(c()); // 5

这就是一个非常典型的闭包了。而且为什么a原创内容,盗版必究。【本文受版权保护】lert(c())两次的值不同,我们还会【本文首发于唐霜的博客】【关注微信公众号:wwwtangshuangnet】在下面解释到。

【访问 www.tangshuang.net 获取更多精彩内容】【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。【转载请注明来源】

为了让你更加明晰的和你曾经开发过的案例联本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】系在一起,我们来看我们曾经做过的这样的事【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net

【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】
define(function() {
  var age = 10;
  function getAge() {
    return age;
  }
  function grow() {
    age ++;
  }
  return {
    age : getAge,
    grow : grow
  };
});

这是我们在require.js中的一种写【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。法,把它还原为我们熟悉的闭包模式:

【未经授权禁止转载】【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【转载请注明来源】
function Cat() {
  var age = 10;
  function getAge() {
    return age;
  }
  function grow() {
    age ++;
  }
  return {
    ageAge : getAge,
    grow : grow
  };
};
var cat = Cat();
var age = cat.getAge();
alert(age); // 10
cat.grow();
age = cat.getAge();
alert(age); // 11

从内存看闭包转载请注明出处:www.tangshuang.net

【本文首发于唐霜的博客】未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。

现在,我们就要来解释为什么上面的aler【原创不易,请尊重版权】【原创不易,请尊重版权】t()两次的结果不同的原因了。

【作者:唐霜】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。

首先,我们来看下普通的函数声明和使用过程【本文受版权保护】原创内容,盗版必究。中内存的变化:

原创内容,盗版必究。【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net
function fun(a,b) {
  return a+b;
}
alert(fun(1,2));
alert(fun(3,4));

上面是我们没有遇到闭包的情况,内存我们这【作者:唐霜】未经授权,禁止复制转载。样来画(注意,我这里只是抽象的画出内存变【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net化,而不是真实的javascript内存【转载请注明来源】本文版权归作者所有,未经授权不得转载。机制。)

【作者:唐霜】【转载请注明来源】【未经授权禁止转载】

cosfafsdgsfdgdsf

转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。

在每一次执行完fun()之后,fun()【访问 www.tangshuang.net 获取更多精彩内容】【本文受版权保护】函数的执行环境被释放(回收机制)。

【原创不易,请尊重版权】原创内容,盗版必究。【原创内容,转载请注明出处】

接下来我们来看一个闭包:【版权所有,侵权必究】

本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。未经授权,禁止复制转载。
function fun(a) {
  return function(b){return a + b;}
}
var add = fun(2);
alert(add(2));
alert(add(4));

上面就出现闭包了,注意,我们这里出现了一著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。个add变量。

著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】

cosfafdsf2

转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。原创内容,盗版必究。未经授权,禁止复制转载。

在后两步中,实际上fun(2)部分没有任【原创内容,转载请注明出处】本文版权归作者所有,未经授权不得转载。何变化,所变的,则是在内部函数所对应的内本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。存区域中有变化。细心的你,可能会发现这里本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】面的问题所在,当执行完add(2)之后,【版权所有,侵权必究】未经授权,禁止复制转载。fun对应的内存没有被释放掉,而它的内部原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】函数,也就是function(2)被释放本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net掉了,在执行add(4)的时候,仅仅重新【作者:唐霜】原创内容,盗版必究。运行了内部函数。如果连fun()对应的内【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】存出现了变化怎么办?我们来看下面的例子:

著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。
function fun() {
  var b = 2;
  return function(a) {
    return a + ++b;
  };
}
var c = fun();
alert(c(1)); // 4
alert(c(1)); // 5

注意,这可是个非常典型的闭包的例子,它有【作者:唐霜】【原创内容,转载请注明出处】一个局部变量b,我们来看它的内存图。

本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。

cosf344afdsf

【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】未经授权,禁止复制转载。【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】

注意第2、3、4步中内存的变化。第2步时【作者:唐霜】【原创不易,请尊重版权】,我们仅仅将fun()赋给变量c,这个时【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。候,内部函数function(a)并没有【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。被执行,所以++b也没有被执行,b的值还【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。是2。但是第3步开始,++b被先执行,+【原创不易,请尊重版权】未经授权,禁止复制转载。+b的意思是先自加,再进行运算,和b++原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net是不同的,如果是b++,虽然c(1)的最【原创内容,转载请注明出处】【版权所有】唐霜 www.tangshuang.net终结果还是为4,但是在c(1)执行开始时【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net,b应该为2,执行完之后才是3。

【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。

奇妙的事情发生了,在内部函数中,++b导【未经授权禁止转载】【版权所有,侵权必究】致了局部变量值发生了变化,b从2变成了3著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】,而且,内存并没有被释放,fun()的执【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】行环境没有被销毁,b还被保存在内存中。到著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】第4步时,b的初始值是3,经过++b 之【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net后,变成了4。

【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【转载请注明来源】【转载请注明来源】转载请注明出处:www.tangshuang.net

这个内存分析非常形象的把闭包概念中,关于原创内容,盗版必究。【作者:唐霜】“突破作用域限制”这个点描述的非常清楚,原创内容,盗版必究。【未经授权禁止转载】原本按照作用域的限制,函数的局部变量不能【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】被外部环境访问,更不能被修改,但是闭包却原创内容,盗版必究。原创内容,盗版必究。使得外部环境不仅可以读取到局部变量的内容著作权归作者所有,禁止商业用途转载。【作者:唐霜】,甚至可以修改它,深入一点就是:闭包会导致闭包函数所涉及到的非自身定义的本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net变量一直保存在内存中,包括其父函数在内的【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】相关环境都不会被销毁。

本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【转载请注明来源】本文作者:唐霜,转载请注明出处。

闭包到底有什么用?未经授权,禁止复制转载。

【原创不易,请尊重版权】原创内容,盗版必究。【原创不易,请尊重版权】【版权所有,侵权必究】

说了这么多,那闭包到底有什么用,我们为什【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net么要使用闭包呢?从上面的阐述中,你应该已著作权归作者所有,禁止商业用途转载。【作者:唐霜】经知道了闭包的唯一作用:突破作用域限制。【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】那如何使用这个作用为程序服务呢?

转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】

常驻内存,意味着读取速度快(,当然,内存转载请注明出处:www.tangshuang.net【未经授权禁止转载】花销也大,导致内存溢出)。常驻内存,意味未经授权,禁止复制转载。【原创内容,转载请注明出处】着一旦初始化以后,就可以反复使用同一个内【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。存中的某个对象,而无需再次运行程序。而这【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】一点,是很多插件、模块的设计思想。

原创内容,盗版必究。转载请注明出处:www.tangshuang.net原创内容,盗版必究。【本文首发于唐霜的博客】【版权所有,侵权必究】

最好的例子就是上文我举得那个define【本文首发于唐霜的博客】【本文受版权保护】()的例子,后面用我们今天所了解的形式去【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】实践之后,你就会发现原来可以把funct本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。ion当做一个其他语言中的class来对著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net待,cat.getAge(), cat.未经授权,禁止复制转载。原创内容,盗版必究。grow()这样的操作是不是很符合我们在本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】编程中的使用习惯呢?一旦一个产生之后,这【转载请注明来源】转载请注明出处:www.tangshuang.net个cat就一直在内存中,随时可以拿出来就转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。用,它就是一个实例化对象。

本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】

为了更形象,我们来创建一个简单的代码块:

【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】
function Animal() {
	this.age = 1;
	this.weight = 10;
	return {
		getAge: function() {
			return this.age;
		},
		getWeight: function() {
			return this.weight;
		},
		grow: function() {
			this.age++;
			this.weight = this.age * 10 * 0.8;
		}
	};
}

function Cat() {
	var cat = new Animal(); // 继承
	cat.grow = function() {
		cat.age++;
		cat.weight = cat.age * 10 * 0.6;
	}
	return cat;
}

var cat1 = new Cat();
alert(cat1.getAge());
cat1.grow();
alert(cat1.getAge());

为什么要举这个例子呢,因为我想让你想象这原创内容,盗版必究。【转载请注明来源】样一种场景,如果没有闭包怎么办?

【未经授权禁止转载】【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】

没有闭包是这样的一种状态:函数无法访问自【原创内容,转载请注明出处】【原创内容,转载请注明出处】己父级(祖先,全局)对象的变量。比如:

【原创不易,请尊重版权】原创内容,盗版必究。【转载请注明来源】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net
var a = 1;
function add() {
  return ++a; // 如果没有闭包机制,会undefined报错
}

这种情况怎么办?必须以参数的形式传入到函原创内容,盗版必究。未经授权,禁止复制转载。数中:

著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net
var a = 1;
function add(a) {
  return ++a;
}
alert(add(a)); // 2

如果是这样,就很麻烦了,你需要在每一个函【本文受版权保护】本文版权归作者所有,未经授权不得转载。数中传入变量。而更麻烦的是,没有了作用域【本文首发于唐霜的博客】【原创内容,转载请注明出处】的突破,例如:

【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。
function Cat() {
  age = 1;
  function getAge(age) {
    return age;
  }
  function grow(age) {
    age ++;
  }
  return {
    getAge : getAge,
    grow : grow
  }
}
var cat = new Cat();
cat.grow();
alert(cat.getAge()); // 1,没有被修改

这种情况下,我们无论如何都无法使用这种办本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。法来实现我们的目的。唯一能够实现的,就是原创内容,盗版必究。【本文受版权保护】按照下面这种方法:

原创内容,盗版必究。未经授权,禁止复制转载。未经授权,禁止复制转载。
var cat = {
  age : 1,
  weight : 10,
  grow : function() {
    this.age ++;
    this.weight += 3;
  }
};
var cat1 = cat;
alert(cat1.age);
cat1.grow();
alert(cat1.age);

我们聪明的使用到了this关键字,但是这【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。样一个坏处是,age, weight这些原创内容,盗版必究。【本文受版权保护】属性直接暴露给外部,我们只需要执行 ca未经授权,禁止复制转载。【本文受版权保护】t1.age = 12; 就可以马上让c【本文受版权保护】【本文首发于唐霜的博客】at长到12岁,而体重却没任何变化。

【未经授权禁止转载】原创内容,盗版必究。【转载请注明来源】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。

总结而言,闭包可以带来这么几个方面的应用本文版权归作者所有,未经授权不得转载。【作者:唐霜】优势:

【作者:唐霜】转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net
  • 常驻内存,加快运行速度【版权所有】唐霜 www.tangshuang.net
  • 【本文首发于唐霜的博客】未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。
  • 封装【关注微信公众号:wwwtangshuangnet】
  • 著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【转载请注明来源】【本文首发于唐霜的博客】

闭包使用中的注意点【版权所有,侵权必究】

【本文受版权保护】【本文首发于唐霜的博客】【转载请注明来源】本文作者:唐霜,转载请注明出处。

除了上面提到的内存开销问题外,还有一个需【原创不易,请尊重版权】转载请注明出处:www.tangshuang.net要被注意的地方,就是闭包所引用的外部变量【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。,在一些特殊情况下会存在与期望值不同的误【作者:唐霜】原创内容,盗版必究。差。

【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】【转载请注明来源】
function init() {
       var pAry = document.getElementsByTagName("p");
       for( var i=0; i<pAry.length; i++ ) {
          pAry[i].i = i;
          pAry[i].onclick = function() {
             alert(this.i);
          }
       }
}

在上面这段代码中,你希望通过一个循环,来未经授权,禁止复制转载。原创内容,盗版必究。为每一个p标签绑定一个click事件,然【转载请注明来源】未经授权,禁止复制转载。而不幸的是,for循环中使用的闭包函数没【版权所有,侵权必究】【本文首发于唐霜的博客】有让你如愿以偿,在闭包函数中,i被认作p【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】Ary.length,也就是循环到最后i【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】的最终值。为什么会这样呢?  原来,闭包未经授权,禁止复制转载。【未经授权禁止转载】引用变量,而非直接使用变量,“引用”的意未经授权,禁止复制转载。【本文受版权保护】思是将指针指向变量的内容。由于这个原因,【本文首发于唐霜的博客】【版权所有,侵权必究】当i=0的时候,闭包里面的i确实是0,但【原创内容,转载请注明出处】原创内容,盗版必究。是当随着i的值变大的时候,闭包内的i并没著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net有保存当前值,而是继续把指针指向i的内容【原创不易,请尊重版权】【本文受版权保护】,当你点击某个p标签的时候,i的内容实际【未经授权禁止转载】【本文首发于唐霜的博客】上是for到最后i的值。

转载请注明出处:www.tangshuang.net【作者:唐霜】【本文首发于唐霜的博客】【本文受版权保护】转载请注明出处:www.tangshuang.net

同样,这个问题会出现在setTimeou【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。t,setInterval,$.ajax转载请注明出处:www.tangshuang.net【作者:唐霜】等这类操作中,你只要记住,当你绑定操作时未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net,和执行操作时,对应的变量是否已经变化就【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。OK了。

【转载请注明来源】【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【本文受版权保护】

2016-04-16 7656

为价值买单,打赏一杯咖啡

本文价值76.56RMB
已有2条评论
  1. 好人 2018-03-28 19:53

    不是看不懂,是把代码分好块,就一下子明白了

  2. […] 本文中的这个知识点涉及到一个“闭包”的概念,当然这里不是意义上的闭包,但是了解闭包概念,在此处的理解上会容易一些。 […]