摘自开源中国
闭包和作用域是js中比较重要的知识,自己理解起来也有一定的难度

1.Javascript的作用域是函数作用域而非块级作用域

1
2
3
4
5
6
7
8
9
10
11
12
//C语言
#include <stdio.h>
void main()
{
   int i=2;
   i--;
   if(i)
   {
       int j=3;
   }
   printf("%d/n",j);      //use an undefined variable:j
}

这是因为c中的作用域是块级的,j是在if后的{ }中定义的,所以无法访问,然而在js中会是什么情况?

1
2
3
4
5
6
7
    (function(){
        var i=1;
        if(i==1){
            var j=3;
        }
        console.log(j);     //3
    })()

在这里,j是可以访问的,也就是说在一个函数中的任何位置定义的变量在该函数中的任何地方都是可见的

这里提及一句Javascript的作用域链(scope chain),每个函数定义时都会将他的作用域链定设为他定义的环境

1
2
3
4
5
function a(){
    function b(){
        //code
    }
}

这段代码中,b的环境为a,a的环境为全局(window),在b中查找变量时会先搜索自身函数内部,如果不存在就去a的内部查找,还不存在就去全局中查找,若还是找不到就是undefined,这就构成一条链

2.Javascript中变量的作用域分为全局变量和局部变量

在函数内部可以访问全局变量和函数内的局部变量,而在函数外部访问不到函数内的变量,看代码

1
2
3
4
5
var p=11;
function f1(){
   console.log(p);
}
f1();   //11

1
2
3
4
5
function f1(){
    var p=11;
}
f1();
console.log(p);  //ReferenceError: p is not defined

通过这俩段代码可以理解全局变量和局部变量,但是定义局部变量时一定要注意加上var,如果不加上其实定义的是一个全局变量,看代码

1
2
3
4
5
function f1(){
    p=11;
}
f1();
console.log(p);       //11

3.那如何访问函数内部的变量并对它进行操作呢?这里就需要用到闭包

先看看闭包的官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分

看到这句户我不禁想问,这是个啥?

后来参考了一些博客和《Javascript秘密花园》才开始理解,闭包大概就是函数内部的一个函数被外部调用,这样就可以调用内部变量了,比如下面这段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function f1(){
    var p=11;
        return {
            increment: function() {
                p++;
            },
     
            show: function() {
                alert(p)
            }
        }
}
var f=f1();
f.show();      //11
f.increment();
f.show();      //12

先看一下控制台,f是什么样的

这里可以看到,f包含increment和show两个函数,而这两个函数是f1的内部函数所以可以访问p这个变量,在我理解,这里的increment和show就是f1()的两个闭包,用他们就可以从外部调用这个变量

4.闭包可以做些什么?

首先我觉得可以模拟private,就像上面那段代码,这个变量只能在这个函数内部访问,也只有使用了闭包才能访问

第二,和Javascript的垃圾回收有关,这里我还不是很清楚,等到搞明白了再来补上

5.这里有一个要注意的就是循环中使用闭包的问题,这里借用《Javascript秘密花园》里的一个例子

1
2
3
4
5
6
7
8
function f1(){
  for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i); 
    }, 1000);
  }
}
f1();

这段代码输出的是10个10而不是期望的0到9,因为闭包内是对i的引用,然后函数执行时i已经变成了10,这里可以使用自执行的匿名函数

1
2
3
4
5
6
7
8
9
10
11
function f1(){
  for(var i = 0; i < 10; i++) {
     (function(e) {
        setTimeout(function() {
            console.log(e); 
        }, 1000);
    })(i);
 
  }
}
f1();

这里的匿名函数将i作为参数,这里的e会有i的一个拷贝,而引用时是对e的引用,这就避免了上述的问题

Javascript闭包与作用域的更多相关文章

  1. javascript闭包和作用域链

    最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...

  2. JS JavaScript闭包和作用域

    JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外一个函数作用域中变量的函数. 从概念上,闭包有两个特点: 1.函数 2.能访问另外一个函数的作用域中的变量 在ES6之前,JavaS ...

  3. Javascript——闭包、作用域链

    1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...

  4. Javascript闭包与作用域this

    闭包与this的一般用法 关于js函数与闭包的文章想必大家都是在熟悉不过的了,作为js核心亦即最强大的功能之一,每次回过头翻出来看一看,都会有不一样的收获与理解,经典的含义无非如此而已. 1.闭包 1 ...

  5. Javascript中闭包的作用域链

    作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...

  6. 读书时间《JavaScript高级程序设计》三:函数,闭包,作用域

    上一次看了第6章,面向对象.这里接着看第7章. 第7章:函数表达式 定义函数有两种方式:函数声明.函数表达式 //函数声明 function functionName(arg0,arg1,arg2){ ...

  7. javascript(面向对象,作用域,闭包,设计模式等)

    javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...

  8. javascript中闭包与作用域的理解

    很多js的框架与插件编写都用到了闭包,所以,阅读和掌握闭包很有必要.最近学习vue框架时,经常会猜想很多功能的native js实现,很多都应用到了闭包,闭包除了目前已知的一些特性,如:可以保持局部变 ...

  9. javascript深入理解--作用域,作用域链,闭包的面试题解

    一.概要 作用域和作用域链是js中非常重要的特性,关系到理解整个js体系,闭包是对作用域的延伸,其他语言也有闭包的特性. 那什么是作用域?作用域指的是一个变量和函数的作用范围. 1.js中函数内声明的 ...

随机推荐

  1. RabbitMQ-优先级(priority)队列/消息

    就像在日常生活中,事情有轻重缓急一样.我们对于需要处理的消息也有这样的需求. 例如重要的消息我要尽快的得到处理,当然我们可以给重要的消息开个“VIP通道”,但是VIP数量很多,并且VIP也分层次呢? ...

  2. SCOI2015酱油记

    Orz怒跪ns高一进A队,常规还是年级rank1,把gerw都下了一跳. Day1还是拿了点分的,调了半天T3终于调出来了(果然xlk大神可信),加上T1暴力有120(跟爆蛋有什么区别).T1大概有2 ...

  3. JSON字符串与JSON对象的区别及转换

    JSON对象是直接可以使用JQuery操作的格式,和js中的对象一样,可以用对象(类名)点出属性(方法). JSON字符串仅仅只是一个字符串,一个整体,不截取的话没办法取出其中存储的数据,不能直接使用 ...

  4. 美丽的表格样式(使用CSS样式表控制表格样式)

    按照WEB2.0风格,设计了几个表格样式,希望大家喜欢. WEB2.0提倡使用div开布局,但不是要全然放弃使用表格,表格在数据展现方面还是不错的选择. 如今使用介绍使用CSS样式表来控制.美化表格的 ...

  5. Centos6.3 配置yum 163源

    1. 下载repo文件    下载地址:http://mirrors.163.com/.help/CentOS6-Base-163.repo 2. 备份并替换系统的repo文件[root@localh ...

  6. oracle的sql优化

    http://www.cnblogs.com/rootq/archive/2008/11/17/1334727.html

  7. Python之路,Day19 - CMDB、CMDB、CMDB

    Python之路,Day19 - CMDB.CMDB.CMDB   本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT ...

  8. COGS 445. [HAOI2010]最长公共子序列

    #include<iostream> #include<cstdio> #include<cstring> #define mod 100000000 #defin ...

  9. IE8-下背景色半透明滤镜在jquery动画中失效问题记录

    前两天,UIer跟我说,把这些按钮都悬浮在这个图片上!我心中千万头草泥马奔过,图片各种各样.花花绿绿.五颜六色的,这几个按钮也没有多大的光环围绕,用户一眼看上去恐怕会以为这是图片的一部分吧!~~~我假 ...

  10. (转)PHP ob_start() 函数介绍

    php ob_start 与 ob_end_flush() 是 php 的缓冲输出函数. ob_start([string output_callback])- 打开输出缓冲区,所有的输出信息不在直接 ...