函数闭包

来源:互联网 发布:java初级工程师考试 编辑:程序博客网 时间:2024/06/16 03:42

函数的执行依赖于作用域,这个作用域时在函数定义时决定的,而不是函数调用时决定的。函数可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学中就称之为“闭包”。可以说,所有的JavaScript都是闭包

首先熟悉作用域:

var scope = "global";function constructFunction(){    var scope = "local";    function f(){return scope};    return f();}constructFunction();    //local

在上述代码中,执行函数constructFunction,执行函数f,返回函数f的返回值,返回函数constructFunction的值。

作用

闭包可以从外部读取内部数据

var scope = "global";function constructFunction(){    var scope = "local";    function f(){return scope};    return f;}constructFunction()();  //local

JavaScript函数执行的过程中用到了作用域链,作用域链是在函数定义的时候创建的,嵌套函数f定义在作用域链中,其中的变量是局部变量,无论何时何地执行函数f(),这种绑定在执行时都是有效的。换言之,闭包可以捕捉到局部变量,并一直保存下来,看起来就像变量绑定到了在其中定义他们的外部函数

闭包不会破坏作用域链。

“外部函数定义的局部变量在函数返回之后就不存在了”这句话在JavaScript中是不对的。
每次调用函数的时候,就会创建一个新的对象来保存局部变量,把整合各对象添加到作用域中。当函数返回的时候,就从作用域链中将这个绑定变量的对象删除。如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,那么他就会被垃圾回收。如果定义了一个嵌套函数,每个嵌套的函数都对应一个作用域链,并且这个作用域链指向一个变量绑定对象。但如果这些嵌套的函数对象在外部函数中保存下来,那么他们也会和所指向的变量绑定对象一样被垃圾回收。但是如果这个函数定义了嵌套函数,并将它作为返回值返回或者存储在某个属性中,这是就会有一个外部引用指向这个嵌套的函数,就不会被垃圾回收。

闭包的安全性:将变量放在函数内部,避免将变量重置。

var cnt = (function(){    var count = 0;    return function(){        return count++;    }}());cnt();  //0cnt();  //1

内部私有属性的共享

//constfuncs方法循环创建了十个闭包,存储在数组中,由于这些闭包都是在同一个函数中定义的,所以函数中的变量i共享function constfuncs(){    var funcs = [];    for(var i = 0; i < 10; i++){        funcs[i] = function(){return i}    }    return funcs;}var funcs = constfuncs();funcs[5]();

闭包使用注意事项:

  1. 大量的闭包会造成网页的性能问题,容易导致内存泄漏。
  2. 闭包可以改变外部函数的变量
  3. 需要注意this的指向,有调用对象指向对象,没有调用对象就指向window,举个栗子。
var name = "global";var object = {name : "local",getNameFunc : function(){    console.log(this);    return function(){        console.log(this);        return this.name;        };    }};  console.log(object.getNameFunc()());

控制台输出如下:
object调用getNameFunc,这个时候this指向object,执行返回匿名函数function的引用,此时的执行环境就变成了全局,this指向了window。
这里写图片描述

修改:

var name = "global";var object = {name : "local",getNameFunc : function(){    var self = this;    console.log(this);    return function(){        console.log(self);        return self.name;        };    }  };console.log(object.getNameFunc()());

控制台输出:
这里写图片描述

关于JavaScript中的this

0 0