最近看到有人说“前端简单,谁都能学”,我心里就不服气了。真要觉得简单,那就问问他**“JavaScript 有哪些作用域”**,看他能不能答上来?别小看作用域,写代码时稍微搞不清,就可能会踩坑踩到怀疑人生。
为了给那些质疑前端的人一点“颜色”,我决定今天好好总结一下 JS 的作用域,既能梳理知识,也能随时“硬刚”别人!

作用域是指代码中变量和函数的可访问范围。简单说,就是在什么地方可以使用某个变量。
JavaScript 的作用域分为以下几种类型:
我们一一来看。
全局作用域是整个 JavaScript 代码的顶层作用域。任何地方都能访问到的变量或函数,就属于全局作用域。
var globalVar = "这是一个全局变量";
function test() {
console.log(globalVar); // 输出 "这是一个全局变量"
}
test();window 对象是全局对象,所有全局变量会成为 window 的属性。var/let/const 声明的变量(直接赋值),默认也是全局变量,容易造成污染。function badPractice() {
badVar = "Oops!"; // 没有声明,自动成为全局变量
}
console.log(window.badVar); // 输出 "Oops!"建议: 一定要用 let 或 const 声明变量,避免污染全局作用域。
函数作用域是指在函数内部定义的变量,只能在函数内部访问。使用 var 定义的变量具有函数作用域。
function funcScope() {
var localVar = "这是一个局部变量";
console.log(localVar); // 输出 "这是一个局部变量"
}
funcScope();
console.log(localVar); // 报错:localVar is not definedES6 引入了 let 和 const,支持了块级作用域。块级作用域指 {} 包裹的代码块内部的变量,只能在块内访问。
if (true) {
let blockVar = "这是一个块级变量";
console.log(blockVar); // 输出 "这是一个块级变量"
}
console.log(blockVar); // 报错:blockVar is not definedif 语句、for 循环等。for (let i = 0; i < 3; i++) {
console.log(i); // 输出 0, 1, 2
}
console.log(i); // 报错:i is not definedJavaScript 使用词法作用域,这意味着作用域在代码编写时已经确定,而不是在代码执行时动态确定的。
简单来说:嵌套的子作用域可以访问父作用域的变量,但父作用域不能访问子作用域的变量。
function outer() {
let outerVar = "外部变量";
function inner() {
console.log(outerVar); // 输出 "外部变量"
}
inner();
}
outer();即使将 inner() 函数拿到其他地方执行,它仍然记得它定义时的作用域。
function outer() {
let outerVar = "外部变量";
return function inner() {
console.log(outerVar);
};
}
const innerFunc = outer();
innerFunc(); // 输出 "外部变量"这也是 闭包 的基础。
不同的作用域类型解决了不同的问题,但也有可能因为作用域管理不当导致 bug。为了更好地记住,可以总结成一句话:
全局作用域负责大家,函数作用域只管函数,块级作用域做自己的事,而词法作用域规则从不变。
最后,牢记 ES6 的 let 和 const 能避免很多作用域相关的坑,用起来更安全。希望这篇文章能帮你理解 JavaScript 的作用域,下次不会再踩类似的坑了!
你在写代码时,有没有遇到类似的作用域问题?欢迎在评论区分享你的经验! 😊