码迷,mamicode.com
首页 > 编程语言 > 详细

作用域闭包《你不知道的JavaScript(上)》

时间:2020-05-16 12:47:30      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:log   span   全局变量   java   col   内部函数   地方   返回   必须   

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

 

function foo() {
    var a = 2;
    function bar() {
        console.log(a); // 2
    }
    bar();
}
foo();
function foo() {
    var a = 2;
    function bar() {
        console.log(a);
    }
    return bar;
}
var baz = foo();
baz(); // 2 朋友,这就是闭包的效果

bar()依然持有对该作用域的引用,而这个引用就叫做闭包。

 

这个函数在定义时的词法作用域以外的地方被调用。

闭包使得函数可以继续访问定义时的词法作用域

var fn;
function foo() {
    var a = 2;
    function baz() {
        console.log( a );
    }
     fn = baz; // 将 baz 分配给全局变量
}
function bar() {
    fn(); // 妈妈快看呀, 这就是闭包!
} 
foo();
bar(); // 2

 


 

function wait(message) {
    setTimeout( function timer() {
        console.log( message );
    }, 1000 );
} 
wait( "Hello, closure!" );

将一个内部函数(名为 timer) 传递给 setTimeout(..),timer 具有涵盖 wait(..) 作用域的闭包, 因此还保有对变量 message 的引用。

wait(..) 执行 1000 毫秒后, 它的内部作用域并不会消失, timer 函数依然保有 wait(..)作用域的闭包。 

 

只要使用了回调函数,实际上就是在使用闭包!

 


 

function CoolModule() {
    var something = "cool";
    var another = [1, 2, 3];
    function doSomething() {
        console.log( something );
    }
    function doAnother() {
        console.log( another.join( " ! " ) );
    }
    return {
        doSomething: doSomething,
        doAnother: doAnother
    };
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3

这个模式在 JavaScript 中被称为模块。 最常见的实现模块模式的方法通常被称为模块暴露,这里展示的是其变体。 

 

模块模式需要具备两个必要条件。

1. 必须有外部的封闭函数, 该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)。 

2. 封闭函数必须返回至少一个内部函数, 这样内部函数才能在私有作用域中形成闭包, 并 且可以访问或者修改私有的状态。 

 

当只需要一个实例时, 可以对这个模式进行简单的改进来实现单例模式:

var foo = (function CoolModule() {
    var something = "cool";
    var another = [1, 2, 3];
    function doSomething() {
        console.log( something );
    }
    function doAnother() {
        console.log( another.join( " ! " ) );
    }
    return {
        doSomething: doSomething,
        doAnother: doAnother
    };
})();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3

 

模块模式另一个简单但强大的变化用法是, 命名将要作为公共 API 返回的对象:

var foo = (function CoolModule(id) {
    function change() {
        // 修改公共 API
        publicAPI.identify = identify2;
    }
    function identify1() {
        console.log( id );
    }
    function identify2() {
        console.log( id.toUpperCase() );
    }
    var publicAPI = {
        change: change,
        identify: identify1
    };
    return publicAPI;
})( "foo module" );
foo.identify(); // foo module
foo.change();
foo.identify(); // FOO MODULE

 

作用域闭包《你不知道的JavaScript(上)》

标签:log   span   全局变量   java   col   内部函数   地方   返回   必须   

原文地址:https://www.cnblogs.com/linxian95/p/10472960.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!