javascript学习笔记---ECMAScript 函数 --闭包(closure)

ECMAScript 最易让人误解的一点是,它支持闭包(closure)。

闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。

简单的闭包实例

在 ECMAScript 中使用全局变量是一个简单的闭包实例。请思考下面这段代码:

var sMessage = "hello world";

function sayHelloWorld() {
  alert(sMessage);
}

sayHelloWorld();

在上面这段代码中,脚本被载入内存后,并没有为函数 sayHelloWorld() 计算变量 sMessage 的值。该函数捕获 sMessage 的值只是为了以后的使用,也就是说,解释程序知道在调用该函数时要检查 sMessage 的值。sMessage 将在函数调用 sayHelloWorld() 时(最后一行)被赋值,显示消息 "hello world"。

复杂的闭包实例

在一个函数中定义另一个会使闭包变得更加复杂。例如:

var iBaseNum = 10;

function addNum(iNum1, iNum2) {
  function doAdd() {
    return iNum1 + iNum2 + iBaseNum;
  }
  return doAdd();
}

这里,函数 addNum() 包括函数 doAdd() (闭包)。内部函数是一个闭包,因为它将获取外部函数的参数 iNum1 和 iNum2 以及全局变量 iBaseNum 的值。 addNum() 的最后一步调用了 doAdd(),把两个参数和全局变量相加,并返回它们的和。

这里要掌握的重要概念是,doAdd() 函数根本不接受参数,它使用的值是从执行环境中获取的。

可以看到,闭包是 ECMAScript 中非常强大多用的一部分,可用于执行复杂的计算。

提示:就像使用任何高级函数一样,使用闭包要小心,因为它们可能会变得非常复杂。

 在来两个例子:

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.

 

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本身
// 但是我们可以设置它的成员

闭包经常用于创建含有隐藏数据的函数(但并不总是这样)。

posted @ 2014-05-29 13:08  yi-  阅读(151)  评论(0编辑  收藏  举报