14 函数-高级
1 匿名函数
这种形式看起来好像是常规的变量赋值语句,即创建一个没有名称的函数(即匿名函数)并将它赋值给变量 add。
这种情况下创建的函数叫做匿名函数(anonymous function),匿名函数有时候也叫拉姆达函数。
2 递归
写一个严格模式下的递归函数。
"use strict" var factorial = (function f(num) { if(num <= 1){ return 1; }else{ return num * f(num - 1); } }); console.log(factorial(5));
3 闭包
闭包是指有权访问另一个函数作用域中的变量的函数。
一个最简单的闭包例子:
function f1(){ var n = 999; nAdd = function(){ n += 1; } } f1(); nAdd();
nAdd是定义在f1内部的,所以能够访问n,运行后,f1中的n会变成1000。
其中的nAdd就是闭包。
我们来验证一下:
function f1(){ var n = 999; nAdd = function(){ n += 1; } function f2() { console.log(n); } return f2; } var result = f1(); result(); // 999 nAdd(); result(); //1000
上面代码中,f2和nAdd都是闭包。
上面代码中,将f2函数定义在f1内部,这样f2就能访问到f1中的变量了。
运行f1,返回f2,即便f1已经运行完毕,这个f2依旧可以访问f1中的变量n,这个f2就是闭包。
可以参考:学习Javascript闭包
再看一段代码:
function compareFun(propertyName) { return function (obj1, obj2) { var value1 = obj1[propertyName]; var value2 = obj2[propertyName];
if(value1 > value2){
return 1;
}else if(value1 < value2){
return -1;
}else {
return 0;
}
} };
var compare = compareFun("age"); var result = compare({name: "a", age: 20}, {name: "b", age: 30}); console.log(result);
在匿名函数从compareFun中被返回后,它的作用域链被初始化为包含compareFun函数的活动对象和全局变量对象。
这样,匿名函数就可以访问在compareFun函数中定义的所有变量,更为重要的是,compareFun函数执行完后,其活动对象也不会销毁,
因为匿名函数的作用域链中仍然在引用这个活动对象。
上面代码的作用域链如下:
4 闭包的缺陷
5 闭包和变量
别忘了闭包所保存的是整个变量对象(variable object),而不是某个特殊的变量。
function compareFun() { var result = new Array(); for(var i = 0; i < 3; i++){ result[i] = function () { return i; } } return result; }; var functionA = compareFun(); console.log(functionA); console.log(functionA[0]); console.log(functionA[1]); console.log(functionA[0]()); console.log(functionA[1]());
运行结果都是3。
因为每个函数的作用域链中都保存着 compareFun函数的活动对象,所以它们引用的都是同一个变量i,而最后i的值是3。
如果要想每个函数返回的是变动的i,怎么做呢?
function compareFun() { var result = new Array(); for(var i = 0; i < 3; i++){ result[i] = function (num) { return function () { return num; }; }(i); } return result; };
看上去好像不太好理解,没事,来个简化版的:
var x = function (num) { return function () { return num; }; }(2); console.log(x); console.log(x());
也就是说,执行x,返回的是匿名函数
执行x(),将参数2赋值给num,并运行匿名函数。
6 闭包中的this问题
为什么执行闭包后,返回的是The Window,而不是My Object呢?
前面曾经提到过,每个函数在被调用时都会自动取得两个特殊变量: this 和 arguments。
内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量(这一点通过3中的图可以看得更清楚)。
当闭包返回后,闭包是在全局环境中运行的,所以,this指的是window对象。
如果是在严格模式下,运行结果是undefined。
因为
那要访问object中的name,怎么办?
上面代码中的this,不再位于闭包中。
当闭包返回后,调用的that是匿名函数中的变量that。