作用域闭包《你不知道的JavaScript(上)》
Posted 依旧那片天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了作用域闭包《你不知道的JavaScript(上)》相关的知识,希望对你有一定的参考价值。
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是当前词法作用域之外执行。
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(上)》的主要内容,如果未能解决你的问题,请参考以下文章
JS你不知道的JavaScript 笔记—— 作用域与闭包 - 编译原理 - LHS - RHS - 循环与闭包 - 模块 - 词法作用域 - 动态作用域