面试题答案
一键面试作用域链工作原理
- 定义:作用域链是JavaScript中用于解析变量和函数标识符的一种机制。它由多个执行上下文的变量对象(VO)或活动对象(AO,函数执行时的VO)组成的链式结构。
- 形成过程:当代码执行进入一个执行上下文(全局上下文或函数上下文)时,会创建一个变量对象,这个对象包含了该上下文中定义的变量和函数声明。如果当前上下文是函数上下文,还会创建arguments对象。然后,当前上下文的作用域链会被初始化为包含该变量对象(活动对象)和外部(父)上下文的作用域链。
- 查找变量:当JavaScript引擎需要解析一个变量名时,它会从当前执行上下文的作用域链的前端(即当前上下文的变量对象)开始查找。如果找到了该变量名对应的属性,就返回该属性的值;如果没有找到,就会沿着作用域链向上查找,直到找到该变量或者到达全局上下文(全局上下文的变量对象查找完毕后,如果还没找到,就返回
undefined
)。
举例说明通过作用域链访问变量
var globalVar = 'global value';
function outer() {
var outerVar = 'outer value';
function inner() {
var innerVar = 'inner value';
console.log(globalVar); // 通过作用域链访问全局变量 globalVar
console.log(outerVar); // 通过作用域链访问外部函数的变量 outerVar
console.log(innerVar); // 访问自身函数的变量 innerVar
}
inner();
}
outer();
在上述代码中,inner
函数内部通过作用域链依次访问了全局变量globalVar
、外部函数outer
的变量outerVar
以及自身的变量innerVar
。
函数内部同名变量不同作用域的访问规则
- 优先访问局部变量:如果在函数内部有一个变量和外部作用域中的变量同名,函数内部会优先访问局部变量。例如:
var num = 10;
function test() {
var num = 20;
console.log(num); // 输出 20,优先访问函数内部的局部变量 num
}
test();
- 访问外部同名变量:如果要访问外部作用域中的同名变量,可以使用闭包或
window
对象(在浏览器环境下,全局变量是window
对象的属性)。例如,使用闭包的方式:
var num = 10;
function outer() {
var num = 20;
function inner() {
console.log(num); // 输出 20,优先访问 outer 函数的局部变量 num
function subInner() {
console.log(num); // 输出 20,优先访问 outer 函数的局部变量 num
function subSubInner() {
var num = 30;
console.log(num); // 输出 30,优先访问 subSubInner 函数的局部变量 num
function accessOuter() {
// 使用闭包访问外部作用域(outer 函数)的 num 变量
var outerNum = num;
return outerNum;
}
console.log(accessOuter()); // 输出 30,这里访问的是 subSubInner 函数内的 num
}
subSubInner();
}
subInner();
}
inner();
}
outer();
如果在浏览器环境下,要访问全局同名变量,可以通过window
对象:
var num = 10;
function test() {
var num = 20;
console.log(window.num); // 输出 10,通过 window 对象访问全局变量 num
}
test();