# 作用域与动态作用域
# 1、作用域
作用域就是程序源代码中定义变量的区域。作用域规定了执行代码对变量的访问权限。js采用词法作用域(lexical scoping)也就是静态作用域。
# 2、静态作用域与动态作用域
静态作用域:函数的作用域在函数定义的时候就决定了。 动态作用域:函数的作用域是在函数调用的时候才决定的。
const value = 1;
function foo(){
console.log(value)
}
function bar(){
const value = 2;
foo();
}
静态作用域下,foo执行时,会先在该函数内查找变量,没有就直接去上一层找,所以找到了value = 1; 动态作用域下,foo执行时,在该函数内没找到,则去调用该函数的那一层找,所以找到了value = 2;
# 3、静态作用域实例
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
两段代码最终打印的都是local scope。 JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。
# 4、执行上下文栈
js引擎并非一行一行分析和执行程序,而是一段一段分析执行。当执行一段代码的时候,会进行一个准备工作。比如第一个例子中的变量提升,和第二个例子中的函数提升。 更详细的说,这个准备工作就是创建一个执行上下文栈,来管理执行上下文,通过压入执行上下文栈,执行完成后推出来执行代码。
var foo = function () {
console.log('foo1');
}
foo(); // foo1
var foo = function () {
console.log('foo2');
}
foo(); // foo2
function foo() {
console.log('foo1');
}
foo(); // foo2
function foo() {
console.log('foo2');
}
foo(); // foo2
每个执行上下文,都有三个重要属性:
- 变量对象
- 作用域链
- this
# 5、变量对象
变量对象是执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。
← 原型与原型链