文章中英模式
布鲁斯前端JS面试题目 - JavaScript 作用域
解析 JavaScript 中的作用域机制、变量传递方式,以及立即执行函数(IIFE)的应用。掌握块级作用域、函数作用域、经典 for 循环问题与解决方案。
文章中英模式
懒得看文章?那就来看视频吧
作用域是什么?
作用域就像是一个变量的「活动范围」,决定了变量在哪里可以被使用。
三种作用域
- 1.
块级作用域
:用{}
包起来的区域 - 2.
函数作用域
:函数内部的区域 - 3.
全局作用域
:最外层的区域
// 块级作用域
{
let x = 1; // 只能在这个大括号内使用
}
console.log(x); // 错误!x 不存在
// 函数作用域
function test() {
var y = 2; // 只能在这个函数内使用
}
console.log(y); // 错误!y 不存在
// 全局作用域
let z = 3; // 到处都可以使用
变量传递的两种方式
1. 传值(基本类型)
- •复制一份新的值
- •修改新变量不会影响原变量
2. 传参考(对象类型)
- •复制的是「地址」
- •修改新变量会影响原变量
// 传值
let a = 1;
let b = a; // 复制一份 1 给 b
b = 2; // 修改 b 不会影响 a
console.log(a); // 还是 1
// 传参考
let obj1 = { x: 1 };
let obj2 = obj1; // 复制的是地址
obj2.x = 2; // 修改 obj2 会影响 obj1
console.log(obj1.x); // 变成 2 了!
IIFE 是什么?
IIFE(立即执行函数)就是一个马上执行的函数,常用来:
- •保护变量不被外面使用
- •解决 for 循环的问题
// 基本用法
(function() {
let secret = '不能说的秘密';
console.log(secret); // 可以印出
})();
console.log(secret); // 错误!外面看不到
🔥 常见面试题目
(一) let
和 var
差在哪?
解答:主要差异有:
- •
let
一定要先声明才能用,var
可以先用后声明 (hoisting提升,用let可以及时发现bug) - •
let
在声明前使用会直接报错,让你知道写错了 - •
let
不会变成全局变量(不会挂在 window 上)
(二)经典的 for 循环面试题 - 以下输出为何?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
解答:会是 3, 3, 3
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 输出:3, 3, 3
为什么会这样?
•var
没有块级作用域
•当 setTimeout
执行时,循环已经跑完了
•此时 i
的值已经是 3
•所以三个 setTimeout
都印出 3
解决方式
1. 使用 IIFE 的解法
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 1000);
})(i);
}
// 输出:0, 1, 2
为什么这样可以?
•IIFE 创造了一个新的作用域
•每次循环都把当下的 i
值传进去
•每个 setTimeout
都有自己的 j
值
•所以可以正确印出 0, 1, 2
2. 使用 let
的解法(最推荐)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// 输出:0, 1, 2
为什么这样可以?
•let
有块级作用域
•每次循环都会创建一个新的 i
•每个 setTimeout
都记住自己那次 i
值
•所以可以正确印出 0, 1, 2
(三)为什么要用 IIFE?
解答:IIFE 创造了一个新的作用域,可以:
- •保护变量不被外面修改
- •让代码更安全、更模块化