最常见的:
function foo() {
alert('hi, js');
}
foo();
用匿名函数:
var foo = function () {
alert('hi, js');
}
foo();
改装一下,给调用的foo()加个括号:
var foo = function () {
alert('hi, js');
}
(foo)();
干脆,连foo的定义也省掉------把foo赋值语句的等号右边的东东、直接替换掉刚才括起来的foo:
(function () {
alert('hi, js');
})();
先看常用的函数:
function sayHello(name) {
var text = 'Hello ' + name;
var sayAlert = function() { alert(text); }
sayAlert();
}
sayHello('Bob');
闭包的例子
一句话描述:
- 闭包是函数的局部变量,在函数return之后,仍然有值, 或者
- 闭包是stack-frame,在函数return的时候,它不会被释放。(就好像'stack-frame'是内存分配、而非处于堆栈!)
下面的代码返回一个function的引用:
function sayHello2(name) {
var text = 'Hello ' + name; // local variable
var sayAlert = function() { alert(text); }
return sayAlert;
}
var say2 = sayHello2('Jane');
say2(); //hello Jane
多数JavaScript程序员能够理解上面代码的函数引用如何返回给变量。请在学习闭包之前理解它。C程序员把函数看做返回的一个函数指针,变量sayAlert和say2分别是函数指针。
C函数指针和JavaScript的函数引用有着本质的不同。在JavaScript,函数引用变量既是一个函数指针,又是一个隐藏的闭包指针。
上面代码拥有闭包,因为函数体内又声明了一个匿名函数 function() { alert(text); } ,参看例子中的sayHello2()。如果你在另一个函数内使用function关键字,闭包就产生了。
在C和其他多数语言,当函数return之后,stack-frame就被销毁了,所有的局部变量也就不能访问了。
在JavaScript中,如果你在函数里声明了函数,在你调用的函数renturn之后,局部变量仍然可以访问。请注意上面的例子,我们调用了变量text,它是函数sayHello2的局部变量。
Example 3
这个例子表明局部变量不是拷贝传递,而是引用传递。在外层函数退出时,它把stack-frame保存在内存。
function say667() {
// Local variable that ends up within closure
var num = 666;
var sayAlert = function() { alert(num); }
num++;
return sayAlert;
}
var sayNumba = say667();
sayNumba(); //667,而不是666
alert(sayNumba.toString());
Example 4
三个函数对某个闭包使用同一个引用,因为它们均在setupSomeGlobals()里声明的。
var gAlertNumber = gIncreaseNumber = gSetNumber = null;
function setupSomeGlobals() {
// Local variable that ends up within closure
var num = 666;
// Store some references to functions as global variables
gAlertNumber = function() { alert(num); }
gIncreaseNumber = function() { num++; }
gSetNumber = function(x) { num = x; }
}
setupSomeGlobals();
//任意、多次 运行下面的函数
gAlertNumber();
gIncreaseNumber();
gSetNumber(5); //把num重新设为 5
gSetNumber(-8888); //把num重新设为 -8888
重新运行setupSomeGlobals(); 就会重新产生一个新的闭包。在JavaScript中,当你在函数里又声明一个函数,外部函数每调用一次,内部函数将再被重新产生一次。
Example 5
当心下面例子的循环:闭包中的局部变量可能和你最初想的不一样。
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push( function() {alert(item + ' ' + list[i])} );
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
// using j only to help prevent confusion - could use i
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
}
testList(); //输出3次:'item3 undefined'
Example 6
下面的例子表明,闭包包含了 在外部函数退出之前、定义的任何局部变量。注意,变量alice实际上在匿名函数之后声明的。匿名函数先被声明:当函数被调用时,它可以访问alice,因为alice在闭包里。
function sayAlice() {
var sayAlert = function() { alert(alice); }
// Local variable that ends up within closure
var alice = 'Hello Alice';
return sayAlert;
}
sayAlice()(); //Hello Alice
alert(alice); //错误:alice不是全局变量,它在函数体内var了
Example 7
下面的例子表明,每次调用会产生各自的闭包。
function newClosure(someNum, someRef) {
// Local variables that end up within closure
var num = someNum;
var anArray = [1,2,3];
var ref = someRef;
return function(x) {
num += x;
anArray.push(num);
alert('num: ' + num +
'\nanArray ' + anArray.toString() +
'\nref.someVar ' + ref.someVar);
}
}
closure1 = newClosure(40, {someVar : 'closure 1'});
closure1(5);
closure2 = newClosure(1000, {someVar : 'closure 2'});
closure2(-10);
小结
读一些说明要比理解上面的例子难得多。我对于闭包的说明以及stack-frame等等在技术上可能不正确 --- 但是它们的确有助于理解
分享到:
相关推荐
匿名函数,也称为拉姆达函数,是一种使用JavaScript函数的强大方式。以下总结了匿名函数的特点: 任何函数表达式从技术上说都是匿名函数,因为没有引用它们的确定的方式; 在无法确定如何引用函数的情况下,递归...
闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下...
深度探讨javascript函数的原型链和闭包
js高级中的函数之闭包函数全解与应用场景(循环闭包,定时器,面试题)
JS中的匿名函数和闭包,详细解释了大家的疑惑,提升大家对的JS的进一步的理解!
JavaScript 中的闭包是指内部函数可以访问外部函数作用域中的变量。它是由于 JavaScript 的函数作用域规则和函数可以作为值传递的特性所产生的。 当一个函数被定义在另一个函数内部时,内部函数会创建一个闭包,这...
学习javascript闭包函数的实用文档,讲解全面、详细。pdf格式,
函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数。本文对javascript函数参数与闭包进行详细分析介绍。需要的朋友一起来看下吧
4) 计算函数依赖的闭包。此步骤不作要求,但要会方法。个人总结:将所有属性元素组成一个集合(域)记为R;求R的所有子集(要用到第二步中的全排列~~~),设其中一个为Ri;对每一个子集求其闭包,记为Ri+;然后求Ri...
js闭包写法学习demo
(转载)JavaScript中匿名函数,函数直接量和闭包.docx
1. 由用户输入函数依赖,当用户输入End时,表示所有依赖都输入完毕。(即函数依赖是由用户自己定的,程序中不能假定某个具体的依赖)。 2. 函数依赖的形式是ABC, ABE这样的形式,为了简单起见,我们假定所有的属性...
当我们写一个参数比较多的函数时,如果有些参数,大部分场景下都是某一个固定值,那么为了简化使用,就可以创建一个新函数,指定我们要使用的函数的某个参数,为某个固定的值;这个新函数就是“偏函数” 2. ...
函数和闭包
本资源讲解了:Dart中的函数 函数的定义 可选参数 默认参数 命名参数 箭头函数 匿名函数 闭包等,含PPT和源代码
本文介绍了js匿名函数和闭包的相关内容,供大家参考,具体内容如下 匿名函数 [removed] //function(){}//会报错 var fun = function(){};//将匿名函数赋值给变量 (function(){})();//匿名函数自执行 function...
浅析javascript语言中的函数闭包现象.pdf
1、JavaScript中定义函数有2钟方法: 1-1.函数声明: 代码如下:function funcName(arg1,arg2,arg3){ //函数体} ①name属性:可读取函数名。非标准,浏览器支持:FF、Chrome、safari、Opera。 ②函数声明提升:指...
12.函数进阶-闭包装饰器.md