JavaScript闭包

来源:互联网 发布:软件开发工程师学习 编辑:程序博客网 时间:2024/06/01 07:27

词法作用域

词法作用域(lexical scope)等同于静态作用域(static scope)。所谓的词法作用域其实是指作用域在词法解析阶段既确定了,不会改变。权威指南里有一句精辟的话是:Javascript中的函数“在定义它们的作用域里运行,而不是在执行它们的作用域里运行”。先看先一段代码.

var foo = 1;function static() {    alert(foo);}/* * 叹号后面跟函数!function * 和加号后面跟函数+function * 都是跟(function(){})();这个函数是一个意思 * 都是告诉浏览器自动运行这个匿名函数的 * 因为!+()这些符号的运算符是最高的 * 所以会先运行它们后面的函数 * */! function() {    var foo = 2;    static();}();//在js中,会弹出1而非2,因为static的scope在创建时,记录的foo是1。

作用域链

看下面代码:

var num = 10;var func1 = function() {    var num = 20;    var func2 = function() {        var num = 30;        alert(num);    };    func2();};var func2 = function() {    var num = 20;    var func3 = function() {        alert(num);    };    func3();};func1();func2();

下面分析一下这段代码:
-> 首先整段代码是一个全局作用域,可以标记为0级作用域链,那么久有一个数组
var link_0 = [ num, func1, func2 ];// 这里用伪代码描述
-> 在这里func1和func2都是函数,因此引出两条1级作用域链,分别为
var link_1 = { func1: [ num, func2 ] };// 这里用伪代码描述
var link_1 = { func2: [ num, func3 ] };// 这里用伪代码描述
-> 第一条1级链衍生出2级链
var link_2 = { func2: [ num ] };// 这里用伪代码描述
-> 第二条1级链中没有定义变量,是一个空链,就表示为
var link_2 = { func3: [ ] };
-> 将上面代码整合一下,就可以将作用域链表示为:

用图像表示为:

这里写图片描述

闭包

有了前面的知识,我们来说说闭包是什么。闭包是指在当前作用域内总是能访问外部作用域中的变量

function createClosure() {    var name = "jack";    return {        setStr: function() {            name = "rose";        },        getStr: function() {            return name + ":hello";        }    }}var builder = new createClosure();builder.setStr();console.log(builder.getStr()); //rose:hello

上面的示例在函数中返回了两个闭包,这两个闭包都维持着对外部作用域的引用,因此不管在哪调用总是能够访问外部函数中的变量。

0 0
原创粉丝点击