词法闭包+作用域

看到一篇介绍JS闭包的文章,写的非常易于理解,转载过来。

原文地址: http://blog.jobbole.com/77078/

词法闭包+作用域

我深信理解如何有效利用闭包和作用域是成为一个伟大JavaScript开发者的关键。
那么…什么是闭包?

简单的说,闭包就是内部函数一直拥有父函数作用域的访问权限,即使父函数已经返回。

可能需要个例子。

var createCounter = function() {
    var count = 0;
    return function() {
        return ++count;
    };
};
 
var counter1 = createCounter();
 
counter1();// 1
counter1();// 2
 
var counter2 = createCounter();
 
counter2();// 1
counter1();// 3


一旦createCounter函数被调用,变量count就被分配一个新的内存区域。然后,返回一个函数,这个函数持有对变量count的引用,并且每次调用的时候执行count加1操作。

注意从createCounter函数的作用域之外,我们是没有办法直接操作count的值。Counter1和Counter2函数可以操作各自的count变量的副本,但是只有在这种非

常具体的方式操作count(自增1)才是被支持的。

在JavaScript,作用域的边界检查只在函数被声明的时候。逐个函数,并且仅仅逐个函数,拥有它们各自的作用域表。(注:在ECMAScript 6中不再是这样,因为let的引入)

一些进一步的例子来证明这论点:

// global scope
var scope = "global";
 
var foo = function(){
    // inner scope 1
    var scope = "inner";
    var myscope = function(){
        // inner scope 2
        return scope;
    };
    return myscope;
};
 
console.log(foo()()); // "inner"
 
console.log(scope); // "global"

关于作用域还有一些重要的事情需要考虑。例如,我们需要创建一个函数,接受一个数字(0-9),返回该数字相应的英文名称。

简单点,有人会这样写:

 var names = ['zero','one','two','three','four','five','six','seven','eight','nine'];
var digit_name2 = function(n){   
    return names[n];
};

但是缺点是,names定义在了全局作用域,可能会意外的被修改,这样可能致使digit_name1函数所返回的结果不正确。那么,这样写:

var digit_name2 = function(n){
    var names = ['zero','one','two','three','four','five','six','seven','eight','nine'];
    return names[n];
};

这次把names数组定义成函数digit_name2局部变量.这个函数远离了意外风险,但是带来了性能损失,由于每次digit_name2被调用的时候,都将重新为names数组定义和分配空间。换个例子如果names是个非常大的数组,或者可能digit_name2函数在一个循环中被调用多次,这时候性能影响将非常明显。

这时候我们面临第三个选择。这里我们实现立即调用的函数表达式,仅仅实例化names变量一次,然后返回digit_name3函数,在 IIFE (Immediately-Invoked-Function-Expression 立即执行表达式)的闭包函数持有names变量的引用。
这个方案兼具前两个的优点,回避了缺点。搞定!这是一个常用的模式用来创建一个不可被外部环境修改“private”(私有)状态。

注:

各种专业文献上的"闭包"(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有父函数内部的子函数才能读取父函数的局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。》这就是Javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值