Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

作用域和执行上下文栈 #9

Open
Enivia opened this issue Nov 24, 2022 · 0 comments
Open

作用域和执行上下文栈 #9

Enivia opened this issue Nov 24, 2022 · 0 comments

Comments

@Enivia
Copy link
Owner

Enivia commented Nov 24, 2022

mqyqingfeng/Blog#3
mqyqingfeng/Blog#4

作用域

思考,下面的代码会打印什么结果?

var value = 1;

function foo() {
  console.log(value);
}
function bar() {
  var value = 2;
  foo();
}

bar();

作用域分为两类:词法作用域、动态作用域。

词法作用域中函数的作用域在函数定义的时候决定(函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,去函数定义时的环境中查询)。
动态作用域中函数的作用域在函数调用的时候决定(函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,去函数调用时的环境中查询)。

JavaScript 采用的是词法作用域,我们可以分析上面代码的执行过程:执行 foo,没有查找到局部变量 value,根据其定义的环境查找上层代码,找到 value 的声明,所以输出结果为 1。

执行上下文栈

JavaScript 创建了“执行上下文栈”来管理函数执行时的上下文。在代码中,每遇到一次函数执行就会创建一个对应的执行上下文栈。

function fun3() {
  console.log("fun3");
}

function fun2() {
  fun3();
}

function fun1() {
  fun2();
}

fun1();

思考,运行上面代码的过程中执行上下文栈会发生什么样的变化?

我们用一个 Stack 模拟执行上下文栈。

JavaScript 在执行代码前,会最先遇到全局代码。所以在执行 fun1() 前就会向栈中压入一个全局上下文栈。

Stack = [GlobalContext];

当执行一个函数时就会创建一个执行上下文并入栈;当函数执行完毕时,就会将函数的执行上下文从栈中弹出。所以执行上下文栈的变化如下:

// 执行 fun1
Stack.push(FunContext<fun1>);
// fun1 中调用了 fun2,所以入栈 fun2 的执行上下文
Stack.push(FunContext<fun2>);
// fun2 中调用了 fun3,所以入栈 fun3 的执行上下文
Stack.push(FunContext<fun3>);

// console.log('fun3')

// fun3 执行完毕
Stack.pop();
// fun2 执行完毕
Stack.pop();
// fun1 执行完毕
Stack.pop();

// JavaScript 接着执行下面的代码,但是 Stack 底层永远有 GlobalContext

思考

结合上面的内容,看看下面的两段代码有什么区别。

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()();

首先看返回结果,根据词法作用域的规则,两个 function f 定义的位置所找到的一定都是局部变量 scope,所以返回值为 "local scope"

再看执行上下文栈

第一段代码:

// 执行 checkscope
Stack.push(FunContext<checkscope>);
// 执行 f
Stack.push(FunContext<f>);
Stack.pop();
Stack.pop();

第二段代码:

// 执行 checkscope
Stack.push(FunContext<checkscope>);
Stack.pop();
// 执行 f
Stack.push(FunContext<f>);
Stack.pop();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant