闭包及其作用

来源:互联网 发布:生意参谋淘宝版 编辑:程序博客网 时间:2024/06/16 21:42

形成

当函数可以记住并访问所在的词法作用域时,(即使函数是在当前词法作用域之外执行的)就形成了闭包

闭包的作用域链:

  1. 自己的作用域
  2. 外部函数的作用域
  3. 全局作用域
通常函数在执行结束后其作用域和变量都会被销毁,但函数返回闭包时,函数的作用域会一直保存到闭包消失。

作用

1. 模仿块级作用域

创建并立即执行一个函数,函数中的变量会立即被销毁,除非将其赋值给了全局作用域中的变量。

2. 在对象中创建私有变量

用闭包实现公有方法,用其访问作用域中的私有变量

var fun = (function () {        var a = 1;        function geta() {            return a;        }        Outer = function () {}        Outer.prototype.publicMethod = function () {            a++;            return geta();        }    })();    var o = new Outer();    o.publicMethod();返回2

使用闭包的注意点

1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

实例

实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
输入例子:
var arr = [1, 2, 3]; var square = function (x) { return x * x; }; var funcs = makeClosures(arr, square); funcs1;

输出例子: 4

直接匿名函数

function makeClosures(arr, fn) {    var funcs = [];    for(var i=0; i        (function(v){            funcs[v] = function(){                return fn.call(null,arr[v]);            }        })(i);    }    return funcs;}

forEach()

function makeClosures(arr, fn) {    var result = new Array();    arr.forEach(function(curr){        result.push(function(){return fn(curr)});    })    return result;}

使用ES5的bind()方法

function makeClosures(arr, fn) {    var result = new Array();    for(var i=0;i        result[i] = fn.bind(null,arr[i]);    }    return result;}

参考《JavaScript高级程序设计》的典型方法

function makeClosures(arr, fn) {    var result = new Array();    for(var i=0;i        result[i] = function(num){            return function(){                return fn(num);            }        }(arr[i]);    }    return result;}

思考题

 var name = "The Window";  var object = {    name : "My Object",    getNameFunc : function(){      return function(){        return this.name;      };    }  };var a = object.getNameFunc;a()();//这里的调用者一直是window,因此输出"The Window";object.getNameFunc()();//这里object.getNameFunc()时调用者是object,但是将object.getNameFunc()作为一个整体,他的调用者是window,是window来调用object.getNameFunc()(),此时调用者是window,因为输出"The Window";
 var name = "The Window";  var object1 = {    name : "My Object",    getNameFunc : function(){      var that = this;      return function(){        return that.name;      };    }  };  object1.getNameFunc()();//这里类似上面object.getNameFunc()时调用者是object的,但是在object1.getNameFunc()的返回函数中,将this赋值给that,因此object1.getNameFunc()()中,this仍然是object,所以输出"My Object",var e = object1.getNameFunc;e()();//这里this一直是window,因此不管如何赋值,都输出"The Window"

下面是this的其他

var name = "The Window";var object = {    name : "My Object",    getNameFunc : function(){        return this.name;    }};object.getNameFunc()//"My Object"(object.getNameFunc)()//"My Object"(object.getNameFunc = object.getNameFunc)()//"The Window"//最后一个object.getNameFunc的值是函数本身。function (){return this.name;}
原创粉丝点击