javascript,普通函数的 this和箭头函数的 this对比
箭头函数和普通函数最大的区别之一是:
- 普通函数的
this:调用时绑定(谁调用,this就指向谁)。 - 箭头函数的
this:定义时绑定(继承自「定义箭头函数时所处的外层作用域」的this),且箭头函数本身没有自己的this,无法被call/apply/bind修改。
// 全局作用域(浏览器中 this 指向 window,Node 中指向 global)
const person = {
name: "张三",
sayNameNormal: function() {
console.log(this.name);
},
// 箭头函数定义在「对象字面量的属性值位置」
sayNameArrow: () => {
console.log(this.name);
}
};
这里面存在一个关键误区:很多人以为箭头函数定义在 person 对象里,外层作用域就是 person—— 但对象字面量不是独立的作用域!
所以,接下来,我们就要搞清楚,什么是独立的作用域?
要搞清楚「独立作用域」的范畴,首先明确核心定义:独立作用域是能创建新的变量 / 标识符查找范围的语法结构,变量在其中声明后不会泄漏到外部,且内部能形成独立的
this 绑定(针对函数)。下面先列出 JS 中所有能创建独立作用域的语法结构,再结合例子对比「有作用域」和「无作用域」的区别,帮你彻底理解。
一、JS 中能创建独立作用域的核心结构
1. 函数作用域(最基础)
所有普通函数(声明式、表达式、匿名函数)都会创建独立的函数作用域,箭头函数继承外层作用域,但本身不创建新作用域。
// 全局作用域
const a = 1;
function fn() {
// 函数独立作用域
const a = 2;
console.log(a); // 输出 2(优先找函数内的 a)
}
fn();
console.log(a); // 输出 1(全局的 a 不受函数内影响)
2. 块级作用域(ES6+)
用
常见的块级作用域场景:
{} 配合 let/const/class/import 声明变量时,会创建块级作用域(仅 var 不遵循块级作用域)。
if/else语句的{}for/while循环的{}switch语句的{}- 直接写的独立
{}块
// 全局作用域
if (true) {
// 块级独立作用域
let b = 3; // let 绑定块级作用域
var c = 4; // var 不绑定块级作用域,泄漏到全局
}
console.log(b); // 报错:b is not defined(块级作用域隔离)
console.log(c); // 输出 4(var 无视块级作用域)
3. 模块作用域(ES6 模块)
ES6 模块(
.mjs 文件或设置 type="module" 的 <script>)会创建独立的模块作用域,模块内的变量默认不暴露到全局。// module.js(模块作用域)
const moduleVar = "模块内变量";
export default moduleVar;
// 主文件
import moduleVar from './module.js';
console.log(moduleVar); // 输出 "模块内变量"
console.log(window.moduleVar); // undefined(模块变量不泄漏到全局)
4. 额外补充:eval 作用域(慎用)
eval() 执行字符串代码时,会创建临时的独立作用域(严格模式下),非严格模式则融合到当前作用域(不推荐使用)。二、对比:无独立作用域的常见结构(重点区分)
这些结构看似有
{},但不会创建新作用域,变量 /this 都会沿用外层作用域:- 对象字面量:
{ key: value }的{}仅用于定义对象属性,无作用域隔离; - 对象方法的简写:
const obj = { fn() {} }里的fn是普通函数(自身有作用域),但obj的{}无作用域; - 解构赋值的
{}:const { name } = person的{}仅用于解构,无作用域;
典型对比例子:
// 1. 对象字面量(无独立作用域)
const obj = {
x: 10,
// 这里的箭头函数继承外层(全局)作用域,因为 obj 的 {} 无作用域
arrowFn: () => {
console.log(this); // 指向全局(window/global)
},
// 普通函数自身有作用域,this 调用时绑定
normalFn: function() {
console.log(this); // 调用时指向 obj
}
};
// 2. 独立 {} 块(有块级作用域)
{
let x = 20; // 块级作用域内的变量
}
console.log(x); // 报错:x is not defined(块级作用域隔离)
三、关键总结:如何快速判断是否有独立作用域?
一个简单的判断方法:
- 看「变量声明」:如果在某个
{}内用let/const声明的变量,外部无法访问 → 有独立作用域; - 看「this 绑定」:如果是函数 / 模块 → 能形成独立的
this绑定(箭头函数除外);如果是对象字面量 → 无独立this绑定。
总结
- 有独立作用域的结构:普通函数(含函数表达式)、ES6 块级作用域(
if/for/{} + let/const)、ES6 模块; - 无独立作用域的常见结构:对象字面量、解构赋值的
{}、仅含var的空{}; - 核心区别:独立作用域会隔离变量(外部无法访问内部
let/const变量),而非独立作用域的{}仅作为语法结构,变量 /this均沿用外层。

浙公网安备 33010602011771号