闭包 我的理解是 能够有权访问另一个函数作用域中变量的函数

通常我们知道 普通的函数在调用完成之后,活动对象不会从内存中销毁,其执行环境的作用域链会被销毁,造成资源的浪费 而闭包的好处就在于执行完就会被回收 不会造成资源的极大的浪费 性能也会相应的提升~

闭包的几种写法

  1. //当只有一个返回的内部函数时候
  2.  
  3. //第一种写法
  4. function test1(a,b){
  5.  
  6. return function(c){
  7. console.log(a + b + c);
  8. }
  9.  
  10. }
  11. var m1 = test1(2,4);
  12. m1(5);
  13.  
  14. //输出 11
  15.  
  16. //第二种写法
  17.  
  18. function test2(a,b){
  19. var name = 'xsdsfsfsdxcxcx';
  20.  
  21. function xx(c){
  22. console.log(a + b + c);
  23. }
  24. return xx;
  25. }
  26. var m2 = test2(2,4);
  27. m2(5);
  28.  
  29. //输出 11

若有多个需要返回的内部函数 可使用对象的方法一一列举出来 又称模块模式

  1. // 多个返回的内部函数
  2. function test2(a,b){
  3. var name = 'xsdsfsfsdxcxcx';
  4.  
  5. function xx(c){
  6. console.log(a + b + c);
  7. }
  8. function ss(){
  9. // js中replace默认只替换查找到的第一个值 若要替换多个值需要使用正则
  10. var _replace = name.replace('x','aa');
  11. console.log(_replace);
  12. }
  13. function allReplace(){
  14. var re = /x/g;
  15. var _replace = name.replace(re,'X');
  16. console.log(_replace);
  17. }
  18. return {
  19. xx : xx,
  20. ss : ss,
  21. allReplace: allReplace
  22. }
  23. }
  24. var m2 = test2(2,4);
  25. m2.ss(); //输出 aasdsfsfsdxcxcx
  26. m2.xx(3); //输出 9
  27. m2.allReplace(); //输出 XsdsfsfsdXcXcX

简单的案例看下 静态方法和实例方法的区别

  1. 1 var test1 = function(){
  2. 2
  3. 3 }
  4. 4 test1.Show = function(){
  5. 5 alert('静态方法!');
  6. 6 }
  7. 7 test1.prototype.Display = function(){
  8. 8 alert('实例方法!');
  9. 9 }
  10. 10
  11. 11 test1.Show(); //静态方法 只能直接用类名进行调用 不能使用this
  12.                        //函数才有prototype属性 对象是没有的
  13.  
  14. 12 test1.Display(); //报错 这是一个是实例方法 必须先实例化后才能进行调用
  15. 13
  16. 14
  17. 15 var Demo = new test1();
  18. 16 Demo.Display(); //实例方法

再来看一段代码

  1. var dom = function(){
  2. var Name = "Default";
  3. this.Sex = "Boy";
  4. this.success = function(){
  5. alert("Success");
  6. };
  7. };
  8.  
  9. alert(dom.Name); //undefined 这是因为每个function都会形成一个作用域 而这些变量声明在函数中 所以就处于这个函数的作用域中 外部是无法访问的 必须new一个实例
  10. alert(dom.Sex); //undefined

再来一段代码

  1. var html = {
  2. Name:'Object',
  3. Success:function(){
  4. this.Say = function(){
  5. alert("Hello,world");
  6. };
  7. alert("Obj Success");
  8. }
  9. };
  10. //html是一个对象,不是函数,所以没有Prototype属性,其方法也都是公有方法,html不能被实例化。
  11. //我们可以这样使用它 html.Name 和 html.Success()
  12. //当然我们也可以将这个对象作为一个值赋给其他变量 比如 var a = html

那么问题来了 我们该如何访问Success方法中的Say方法呢 难道是html.Success.Say()吗? 当然这样式错误的啦  因为在Say方法中又开始了一个新的function形成新的作用域 肯定是访问不到里面的内容啦

得做点修改 比如

  1. 1 var s = new html.Success();
  2. 2 s.Say(); //Hello,world
  3. 3
  4. 4
  5. 5 //或者写在外面
  6. 6 html.Success.prototype.Show = function(){
  7. 7 alert("HaHa");
  8. 8 };
  9. 9 var s = new html.Success();
  10. 10 s.Show();

说了这么多 那么闭包的用途到底是什么呢?

事实上通过使用闭包 我们可以做很多事情 比如模拟面向对象的代码风格 更优雅 更简洁的表达出代码 这是一个有点追求美感的程序员应该做的 而且在某些方面可以提升代码的执行效率

1 匿名自执行函数

  1. var data = {
  2. arr : [2,5,2,4,333],
  3. tree : {}
  4. }
  5. (function(x){
  6. var row,
  7. new_arr = [];
  8. for(var i = 0; i < x.arr.length; i ++){
  9. row = x.arr[i];
  10. new_arr.push(row);
  11. }
  12. return new_arr;
  13. })(data) //输出 [2,5,2,4,333]

创建了一个匿名函数 并立即执行 由于外部无法直接访问内部的变量 因此在函数执行完成后会立刻释放资源 还不会污染全局变量

2 缓存作用

将计算结果缓存在内部 之后再调用的话就可以直接使用

3 封装

  1. var package = function(){
  2. var name = '张三';
  3.  
  4. return {
  5. getName : function(){
  6. return name;
  7. },
  8. setName : function(names){
  9. name = names;
  10. return name;
  11. }
  12. }
  13. }();
  14.  
  15. package.getName(); //张三
  16. package.setName('李四'); // 李四
  17.  
  18. package.name; //undefined

4 类和继承

  1. function Mother(){
  2. var eye = 'default';
  3.  
  4. return {
  5. getName : function(){
  6. return eye;
  7. },
  8. setName : function(newName){
  9. name = newName;
  10. return name;
  11. }
  12. }
  13. }
  14.  
  15. var M = new Mother();
  16. M.getName();
  17. M.setName('beautiful!');
  18.  
  19. var Person = function(){
  20.  
  21. }
  22. //继承
  23. Person.prototype = M;
  24. Person.prototype.Say = function(){
  25. console.log('这是私有方法!');
  26. }
  27. var p = new Person();
  28. p.getName();
  29. p.setName('hah');
  30. p.Say();

理解js中的闭包的更多相关文章

  1. java程序员理解js中的闭包

    1.闭包概念: 就是函数内部通过某种方式访问一个函数内部的局部变量 再次理解: 闭包产生原因: 1.内部函数引用了外部函数的变量 作用:延长局部变量的生命周期 让函数外部可以调用到函数内部的数据 利用 ...

  2. 彻底理解js中的闭包

    闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,那么什么是闭包呢?它又有什么用呢? 我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用 ...

  3. javascript理解js中的闭包

    在javascript中变量有其作用域,如果在函数内部var一个变量,那么在函数外部一般情况下是不能被引用的. function outerFun() { ; alert(a); } ; outerF ...

  4. js中的闭包之我理解

    闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的 ...

  5. js中的闭包理解一

    闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的 ...

  6. js中的闭包理解

    闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的 ...

  7. 怎么理解js中的事件委托

    怎么理解js中的事件委托 时间 2015-01-15 00:59:59  SegmentFault 原文  http://segmentfault.com/blog/sunchengli/119000 ...

  8. 详解js中的闭包

    前言 在js中,闭包是一个很重要又相当不容易完全理解的要点,网上关于讲解闭包的文章非常多,但是并不是非常容易读懂,在这里以<javascript高级程序设计>里面的理论为基础.用拆分的方式 ...

  9. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

随机推荐

  1. AS:加载新版本的SWF文件。

    方案一: 文件名+版本号,区别对待不同的版本控制,有设定值后会加上_v_x的后缀名.如:加载主文件 main.swf, 被命名为:Main_v_60.swf . 方案二: loader.load(ne ...

  2. Android中全局Application的onCreate多次调用问题

    String processName = OsUtils.getProcessName(this, android.os.Process.myPid()); if (processName != nu ...

  3. intval()和(int)转换使用与区别

    <?php echo "<br/>数值强制转换:"; $string="2a"; $string1=intval($string); echo ...

  4. icacls备份与还原ACL列表(NTFS权限)--Robocopy

    icacls c:\windows\* /save AclFile /T- 将 c:\windows 及其子目录下所有文件的 ACL 保存到 AclFile. icacls c:\windows\ / ...

  5. ARM&Linux 下驱动开发第三节

    后台驱动代码如下:比较昨天的,添加了读写指针位置移动操作 #include<linux/init.h> #include<linux/module.h> #include< ...

  6. 使用GLSL实现的海洋效果 【转】

    http://bbs.osgchina.org/viewthread.php?tid=342&extra=page%3D3 虽说自己原创的部分并不算多,不过总算是调试通过了,中间有多次严重的死 ...

  7. jq获取表单值与赋值代码

    jq获取表单值与赋值代码 jq获取表单值与赋值代码 $("#keyword")[0].value = ""; /*获得TEXT.AREATEXT的值*/ var ...

  8. Ubuntu 14.04 Android 使用Maven二 创建自己的Mavenproject

    依据https://code.google.com/p/maven-android-plugin/wiki/GettingStarted 介绍,有两种方法能够创建Mavenproject. 第一种方法 ...

  9. codeblocks中添加-std=c99

    早上用codeblocks编译一个c文件,出现这样一个编译错误: +'for'+loop+initial+declarations+are+only+allowed+in+C99+mode 原来cod ...

  10. 终端I/O之stty命令

    所有的终端选项标志,在程序中都可用tcgetattr和tcsetattr函数(http://www.cnblogs.com/nufangrensheng/p/3576682.html)进行检查和更改. ...