Comments (4)
词法化 (也叫单词化)
大部分标准语言编译器的第一个工作阶段叫做 词法化。
词法化的过程会对源代码中的字符进行检查,如果是有状态的解析过程,还会赋予单词语义。
了解了词法化后,下面我们就该说说正题了
词法作用域
词法作用域就是定义在词法阶段的作用域。词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的。
词法作用域意味着作用域是由书写代码时函数声明的位置来决定的。
所以词法作用域又叫静态作用域。
因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar(); // 1
from myblog.
JavaScript闭包
当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用 域之外执行。
直接上一个示例代码:
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo(); // 拿到该函数所在词法作用域中的嵌套函数(可以访问外层函数中的变量)
baz(); // 2 —— 这就是闭包的效果
我们将 bar 所引用的函数对象本身当作返回值,然后赋值给变量 baz 并调用 baz(),实际上只是通过不同的标识符引用调用了内部的函数 bar()。
通常foo() 执行后, foo() 的整个内部作用域都被销毁,引擎的垃圾回收机制会回收不再使用的内存空间。
而闭包的神奇之处就在于阻止这个事情的发生。实际上内部作用域依然存在,没有被回收,因为bar()函数还在使用。
拜 bar() 所声明的位置所赐,它拥有涵盖 foo() 内部作用域的闭包,使得该作用域能够一 直存活,以供 bar() 在之后任何时间进行引用。
bar() 依然持有对该作用域的引用,而这个引用就叫作闭包。
function foo() {
var a = 2;
function baz() {
console.log( a ); // 2
}
bar( baz ); // 1.把内部函数baz传递给bar
}
function bar(fn) {
fn(); // 2.当调用的时候还可以访问a,这就是闭包!
}
var fn;
function foo() {
var a = 2;
function baz() {
console.log( a );
}
fn = baz; // 将 baz 分配给全局变量
}
function bar() {
fn(); // 这就是闭包!
}
foo();
bar(); // 2
无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。
from myblog.
常见的闭包
- 定时器函数setTimeout
function wait(message) {
setTimeout( function timer() {
console.log( message );
}, 1000 );
}
wait( "Hello, closure!" );
- 循环与闭包
for (var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
console.log => 5次6
在上面代码中,i是定义在全局作用域中的一个变量,定时器的回调函数会在所有的循环执行完毕后才执行的,此时内存中的变量 i 的值等于6,
稍加改进,我们让定时器函数立即执行
for (var i=1; i<=5; i++) {
(function(j) {
setTimeout( function timer() {
console.log( j );
}, j*1000 );
})( i );
}
from myblog.
利用闭包实现的模块化
function foo() {
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 coolModule = foo();
coolModule.doSomething(); // cool
coolModule.doAnother(); // 1 ! 2 ! 3
利用闭包,我们可以把函数内部的方法暴露出来,可以在其他地方引用。
from myblog.
Related Issues (20)
- 开发自己的cli工具 HOT 1
- 常用的ES6、ES7、ES8特性 HOT 3
- 在浏览器中输入URL地址到页面显示出来中间发生什么了呢? HOT 3
- 他强由他强,清风拂山岗 HOT 6
- 排序算法
- JavaScript继承 HOT 7
- 工作遇到的配置问题 HOT 2
- js触发子元素事件,而不触发父元素事件(阻止事件冒泡) HOT 2
- HTML input中type='file' Accept的值
- 二叉树心法秘籍
- 初探二叉树
- HTTPS初探 HOT 1
- 基于node的文件上传和下载 HOT 1
- axios拦截器处理重定向
- two sum
- 千分位格式化
- React生命周期和hock 的一些使用心得 HOT 1
- RN的TouchableOpacity的使用笔记
- 微信授权登录解密手机号失败
- moment.js工作中常用的api
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from myblog.