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。

posted on 2017-05-01 17:09  modDx  阅读(164)  评论(0编辑  收藏  举报

导航