引言
1.JS 引擎
JS能在浏览器的v8引擎和Node引擎(v8)上运行
JS的执行
1.v8 会先读取代码,并不会第一时间执行,而是要先编译(梳理)
2.然后进行分词:将代码拆成一个一个的词法单元
3.接着进行解析/语法分析:将词法单元组织成一个语法树 AST (抽象语法树 Abstract Syntax Tree)
4.最后执行:根据 AST 生成代码执行
什么是作用域?
作用域(Scope) 是 JS 中用来管理变量访问范围的规则,它决定了哪些变量可以在哪里被访问。
JS中的三种作用域
1.全局作用域
在整个程序中都能访问的变量
var a = 10; // 全局变量
function foo(){
console.log(a); // 可以访问变量a
}
foo();
console.log(a); // 可以访问变量a
这一整个程序所在就是一个全局作用域
2.函数作用域
在函数内部声明的变量,只能在函数内部访问
function foo(b){ //形参b在函数内部
var a = 10; //函数内部变量
console.log(a); //可以访问变量a
}
foo(b);
console.log(a); // 不能访问变量a
function foo(){}会生成一个函数作用域,函数内部声明的变量,函数外部无法访问
3.块级作用域(ES6+)
使用 let 或 const 在 {} 块内声明的变量
{
let a = 10; // 块级变量
const PI = 3.14;
console.log(a); // 可以访问变量a
}
console.log(a); // 不能访问变量a
let 或 const + {} 会形成块级作用域
let不会带来声明提升(var声明的变量如果在调用后面,v8会在将代码拆分时将变量声明提到作用域顶部,这叫声明提升)
const 声明的是常量,不能重新赋值
作用域链
在v8的执行过程中,查找一个变量时,会先在当前作用域中查找,如果找不到,就回去外层作用域中查找,直到找到全局作用域,还是找不到,就会报错
var c = 100;
function foo(){
var b = 10;
if(true){
let a 1;
console.log(a); // 先找内层作用域
console.log(b); // 内层找不到,向外层找
console.log(c); // 继续向外,找到全局作用域
}
}
foo()
总结
1.三种作用域类型
| 类型 | 声明方式 | 作用范围 | 特性 |
|---|---|---|---|
| 全局作用域 | 函数外声明 | 整个程序 | 挂载到 window,易污染 |
| 函数作用域 | 函数内声明 | 函数内部 | 私有性好 |
| 块级作用域 | let/const+{} | 块内有效 | ES6+ 新增 |
2.关键特性
声明提升:var 会提升到作用域顶部
console.log(a);
var a = 10;
在执行时
var a;
console.log(a);
a = 10;
let/const有暂时性死区
var a = 100;
if(true){ // 暂时性死区
console.log(a);
let a = 10;
}