JavaScript函数作用域指function内声明的变量、函数仅在该函数内可访问;仅function创建作用域,{}不创建;var受函数作用域和变量提升影响,let/const为块级作用域;闭包依赖函数作用域但易致内存泄漏。
JavaScript 函数作用域指的是:在 function 内部声明的变量、函数,**默认只能在该函数内部被访问**,外部无法直接读取或修改。
function,不认 {}
很多人误以为用花括号 {} 就能创建作用域,但在 JavaScript(ES5 及之前)中,只有 function 声明会创建新的作用域。if、for、while 里的 {} 不构成作用域边界。
if (true) {
var x = 10;
}
console.log(x); // 输出 10 —— x 泄露到外层作用域了
而换成 function 就完全不同:
function foo() {
var y = 20;
}
foo();
console.log(y); // ReferenceError: y is not defined
var 声明受函数作用域约束,但存在变量提升(hoisting)let 和 const 是块级作用域,不受此规则限制 —— 它们属于 ES6 的新机制,和传统函数作用域是两套逻辑this,但它**完全继承外层函数作用域**,不会创建新作用域var 在函数内多次声明不会报错,但行为容易误判由于 var 存在变量提升 + 函数作用域,下面代码实际运行效果常让人困惑:
function bar() {
console.log(a); // undefined(不是 ReferenceError)
var a = 1;
if (false) {
var a = 2; // 这行声明会被提升,但赋值不会
}
console.log(a); // 1
}
var a 都被提升到 bar 顶部,等价于开头就写了 var a;
if (false
) 不执行,var a = 2 的声明仍生效(只是赋值跳过)undefined 的常见原因闭包本质是:内部函数引用了外部函数的变量,而外部函数执行完毕后,这些变量**因被内部函数持有而未被释放**。
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const inc = createCounter();
console.log(inc()); // 1
console.log(inc()); // 2
createCounter() 都生成一个独立的词法环境,count 被保留在该环境中var 声明的变量在循环中创建闭包时,容易所有闭包共享同一个变量(经典 for + setTimeout 问题)函数作用域看似简单,但和变量声明方式(var/let/const)、执行上下文、闭包生命周期紧密耦合。真正难的不是定义,而是判断某个变量在哪个时刻、被谁持有、能不能被回收。