理解js中的闭包

来源:互联网 发布:日本磁悬浮知乎 编辑:程序博客网 时间:2024/04/20 19:00

js的闭包比较抽象,主要涉及到js的几个其他的特性:作用域链,垃圾回收机制,函数嵌套,等等。
首先,来理解一下作用域链。所谓作用域链,就是寻找使用到的变量的索引。其内部规则为:函数自身变量放在最前边,把父级函数中的变量放在其次,以此类推到全局变量为止。当函数中需要查询一个变量的值时,js会沿着作用域链查找,一旦找到,不再继续;如果没有找到,返回undefined。
其次,理解一下js的内存回收机制。一般情况下,一个函数在执行时会为其定义的变量划分内存空间,当函数执行完,这些变量就会被回收。但是存在一个函数中嵌套另一个函数的情况,内部函数可能会调用外层函数的变量,这时,外层函数的变量就不能被js回收,所以js解释器在遇到函数定义的时候,会自动把函数和他所需要的外部变量一起保存起来。也就是构建一个闭包。
下面通过一个例子理解闭包的作用:
我们知道,函数内部的局部变量无法在外部访问,那么怎样才能访问到函数内部的局部变量呢。可以在函数内部嵌套函数,然后把嵌套函数返回。这样,我们就能拿到函数内部的局部变量了。

function fun(){    var value = "inner";    function func(){        console.log(value);    }    return func();}fun();

以上得代码,其实就是闭包。本质上,闭包就是将函数内部和函数外部连接起来的桥梁。
以下是闭包的另一个例子:

var result = new Array();function foo(){    for (var i = 0 ; i < 3 ; i++ ){        result[i] = (function(i){            return function () {                console.log(i);            }        })(i);    }}

测试

foo();result[0]();//0result[1]();//1result[2]();//2

如果不使用闭包,输出都是3.

下面总结一个闭包的作用:

1 匿名自动执行函数
很多情况下,函数只要执行一次,比如界面初始化。这时,就可以使用闭包,一方面,局部变量很快会被释放,另一方面,不会污染全局变量。

(function(){    for (var j = 0 ; j < 5 ; j++){        console.log(j);    }})();console.log(j);//j不会获取到

2 面向对象,模拟类,封装

function People(){    var username ;    this.getUsername = function(){        return username;    }     this.setUsername = function(name){        username = name ;    }}var p = new People();p.setUsername("zhangsan");console.log(p.getUsername()); //zhangsan

使用闭包的注意点:
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。
解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心。

最后,写一道思考题看看你是否理解了闭包:

var name = "Outer";var object = {    name: "Inner" ,    getName: function(){        return this.name;    };};console.log(object.getName());
var name = "Outer";var object = {    name: "Inner" ,    getName: function(){        return function(){            return name;        };    };};console.log(object.getName()());

两者有什么区别?
第一个输出:Inner
第二个输出:Outer

1 0
原创粉丝点击