JS 中的执行上下文(简称 上下文)决定了变量或函数可以访问哪些数据,以及他们的行为,每个上下文都有一个关联的变量对象(variable object)。所有的上下文中定义的变量和函数都存在于这个对象上(代码无法访问变量对象,但后台会用到它)
变量类型和执行上下文
全局上下文
函数上下文
作用域访问
const { log } = console;
const variable = "global variable"; // 最外层
const outterFn = () => {
const variable = "outterFnVariable"; // 2 可以注释这里和 1 看看,log 又打印啥
const innerFn = () => {
// innerFn 内部可以访问当前块和父级块以上的变量和函数
const variable = "innerFnVariable"; // 1 可以注释这一行看看,log 啥
/**
* 当前的上下文的变量对象上就可以找到值为 innerFnVariable 的 variable 变量
* 如果当前函数上下文 (innerFn) 找不到 variable,就会去 它的父级上下文 innerFn 中找是否存在 variable
* 如果 innerFn 的父级上下文都找不到 variable,就会去最外层的全局上下文上找是否存在 variable 的变量
*/
log(`variable [${variable}]`); // log: variable [innerFnVariable]
};
/**
* 当执行到这里的时候 变量对象(记录作用域链的访问顺序的对象) = innerFnContext -> outterFnContext -> globalContext
* 因此 当前的上下文可以访问到当前和父级以上的上下文变量对象所记录的函数和变量
*/
innerFn();
};
outterFn();
作用域链增强
const buildUrl = () => {
const qs = "?name=jakequc";
let url = "";
with (location) { // 这一行就是作用域链增强,这里的上下文仍然是函数上下文
// with 会向作用域前端添加指定的对象 location
url = href + qs; // 因此这里的 href 其实会去找 location.href, qs 会去外部函数作用域中去找
}
return url;
};
buildUrl();