作用域
JavaScript是门动态语言,跟Java不一样,JavaScript可以随意定义全局变量和局部变量,变量会在该作用域下提升,而且JavaScript没有块级作用域。
全局变量就是定义在全局的变量了,局部变量是定义在函数里的变量,每一个函数都是一个作用域,当函数执行时会优先查找当前作用域,然后逐级向上。定义在
if 和 for 语句里的变量,在大括号外面也能访问到,这就是没有块级作用域。
一、预处理 + 作用域解析
JavaScript 的作用域只用两种,一个是全局的,一个是函数的,也称为 全局作用域 和 局部作用域 ;局部作用域 可以访问 全局作用域 。但是 全局作用域 不能访问 局部作用域
有这样一段代码
var a = 1;
function fn1(){
alert(a);
var a = 2;
}
fn1();
alert(a);
这里先揭晓答案:
第一个 alert(a) 弹出 undefined
第二个 alert(a) 弹出 1
1. 预解析(预编译) 全局作用域 (全局词法环境)
// 全局词法环境
// 第1行,遇到 var 关键字,解析到全局的头部
a = undefined
// 第2行,遇到 function 关键字,解析到全局的头部
fn1 = function fn1(){
alert(a);
var a = 2;
}
// 第3行,没有遇到关键字,不解析
// 第4行,没有遇到关键字,不解析
2. 开始执行代码
第1行,遇到表达式 a = 1, a 被赋值成 1
第6行,遇到函数调用 fn1() , ---- 开始 预解析(预编译) 局部-----
3. 预解析(预编译) 局部作用域 (函数词法环境)
// 第3行,没有遇到关键字,不解析
// 第4行,遇到 var 关键字,解析到局部
a = undefined
4. 开始执行 局部 代码
第3行,弹出 undefined
第4行,遇到表达式,把局部 a 改成 2
5. 局部执行完成,继续执行全局
第7行,弹出 1 ,因为全局和局部是两个独立的作用域
二、作用域疑惑之处
1. js没有块作用域
2. js不是动态作用域,js是静态作用域
function f(){
alert(x);
}
function f1() {
var x = 6;
f();
}
function f2() {
var x = 10;
f();
}
f1();
// 执行会报错,因此js不是动态作用域哦
二、作用域链
var a = 10;
function f() {
var x = 100;
function g () {
//
}
g();
}
f();
- 作用域链解析
1. 创建词法环境(window)
2. 加入 a 以及 f函数 ,这时候 【f.scope === window】
3. 进入f函数,创建f函数的词法环境 【f.le => f.scope】
4. 创建f 的词法环境
5. 添加x和 g函数 到f函数的词法环境 【g.scope === f.le】
6. 进入g函数,创建g函数的词法环境 【g.le => g.scope】
g.le -> g->scope -> f.le -> f.scope -> window
三、作用域的本质
var a = 10;
function f() {
var x = 100;
function g () {
//
alert(a);
}
g();
}
f();
我们在g内部使用了变量a,想要找到a,
- 首先在g的词法环境中查找,如果没找到
- 到g.scope 也就是 f的词法环境中查找,如果依旧没找到
- 到f.scope 也就是 全局词法环境中查找。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。