js闭包相关

来源:互联网 发布:周晨晞的淘宝店叫什么 编辑:程序博客网 时间:2024/06/14 13:30

参考文章:深入理解javascript原型和闭包(完结) ,链接里的内容讲解的很详细。我的这篇文章为了尽量把结合自己的理解用文字记录下来。

说闭包之前,要提到变量和作用域。

变量分为全局变量和局部变量。全局变量也就是函数外部声明的变量,如果一个变量没有用var声明,则会被识别为全局变量。比如name = 'Mike';

局部变量是函数内部的变量,函数执行完之后就消失。

作用域也分为全局作用域和函数作用域,js没有块级作用域。

当函数内部的变量值会优先在函数声明时的作用域寻找,并非调用时候的作用域(很关键)!!!

在内部未找到的变量声明时会到父级作用域中去找,如果还没找到继续往父级找直到全局作用域。

函数如果在自身内部作用域有重新声明,同名的全局变量会失效,采用的是函数内部作用域里的变量。如

var name = 'World!';(function () {    if (typeof name === 'undefined') {        var name = 'Jack';   ///important         console.log('Goodbye ' + name);    } else {        console.log('Hello ' + name);    }})();  //print Goodbye Jack
此时输出为Goodbye Jack说明typeof name ===  'undefined'; 这是因为函数内部重新声明了var name;因此函数值会在函数内部作用域找而非全局作用域。

即使var name ='jack';是在判断之后if (typeof name === 'undefined')才执行的,但是js会把变量的声明提前。相当于

var name;if (typeof name === 'undefined') {name = 'Jack';        console.log('Goodbye ' + name);}


闭包的使用形式一般有两种一是函数作为返回值,二是函数作为参数传递。

函数作为返回值:

function  out(){        var num=0;//内部变量        return  function add(){//通过return返回add函数,可以在out函数外访问了。            num++;            console.log(num);        };    }    var func1=out();//    func1();//实际上是调用add函数, 输出1    func1();//此时是输出是2,说明执行一次过后num值变为1,而普通函数执行完之后,上下文环境(当前作用域的变量)就消失了。    var func2=out();    func2();// 输出1,重新声明的func2起作用,num又重新从1开始,num并非像全局变量改变了。    func2();// 
再来一个返回值的例子:

    var data = [];    for (var k = 0; k < 3; k++) {        data[k] = (function test(x) {            return function () {                console.log(x);            };        })(x);    }    data[0]();//1    data[1]();//2    data[2]();//3

函数作为参数传递

var max=10,    fn = function (x){if(x > max){console.log(x);}    };(function (f){var max=100;f(15);})(fn); //10 去函数创建的作用域取值
上面的例子中,fn函数作为一个参数被传递进入另一个函数,赋值给f参数

通过参考一些文章和自己的尝试,我的理解是闭包像是把函数内的局部变量缓存起来,在函数执行完依旧存在,但是外部又无法直接访问,得通过执行函数来访问。其实就是函数调用完成之后,其执行上下文环境不会接着被销毁。








原创粉丝点击