JavaScript箭头函数与普通函数的this区别及解决方案
本文深入解析JavaScript中this关键字在普通函数与箭头函数中的不同行为。通过对比分析,阐明普通函数this动态绑定的复杂性及常见陷阱,并重点介绍箭头函数如何通过词法作用域简化this取值规则,提供使用建议与代码示例。
前言
引言部分
箭头函数大幅简化了this的获取逻辑。
普通函数与箭头函数的定义
常规函数与箭头函数的对比
常规函数是通过function关键字来定义的:
var hello = function () {
console.log("Hello, Fundebug!");
}
箭头函数则是通过=>符号来定义的:
var hello = () => {
console.log("Hello, Fundebug!");
}
JavaScript中的箭头函数与常规函数不仅存在语法差异,还具备一些细微的区别,其中最为显著的是this的行为。
箭头函数自身不具备this属性,其内部引用的this值源自函数所在的作用域链。
此表述看似简单,但初看可能令人费解,需从基础讲起。
理解JavaScript中的this
究竟什么是this?
关于this的论述已汗牛充栋,为避免混淆,此处不再赘述,仅转引MDN文档内容:this,建议感兴趣者深入阅读,此处仅摘录核心要点。
A function's this keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
JavaScript属于一种较为特殊的语言,其this机制与其他语言存在差异,且该值是否受严格模式("use strict")影响。
this的具体取值为何?
The JavaScript context object in which the current code is executing.
this即代表代码当前执行所处的context object。
全局上下文
In the global execution context (outside of any function), this refers to the global object whether in strict mode or not.
当代码未在任何函数内部执行,而是处于全局作用域时,无论是否启用严格模式,this均指向global对象;在浏览器环境中,this即代表window。
该规则相对易于理解。
普通函数中this的动态绑定
函数上下文
Inside a function, the value of this depends on how the function is called.
函数内部的this值取决于该函数的调用方式,这一规则较为复杂,亦是引发BUG的高发区。
此外,this的值还受到函数是否处于严格模式("use strict")的影响,这确实增加了复杂性……
若读者好奇,可查阅MDN文档,此处不再多言,仅阐述一种简单情形。
As an object method
When a function is called as a method of an object, its this is set to the object the method is called on.
当函数作为对象的方法被调用时,其this值即指向该对象。
var circle = {
radius: 10,
getRadius() {
console.log(this.radius);
}
};
circle.getRadius(); // 打印 10
普通函数this绑定的常见陷阱
采用self = this?
当我们需要在对象方法内部嵌套一个子函数时,this往往会带来实际困扰,想必大家写过类似代码:
// 使用临时变量self
var circle = {
radius: 10,
outerDiameter() {
var self = this;
var innerDiameter = function() {
console.log(2 * self.radius);
};
innerDiameter();
}
};
circle.outerDiameter(); // 打印20
outerDiameter函数作为circle对象的方法,其this值自然指向circle对象。
既然这样,直接书写this.radius岂不更佳?遗憾的是不可行,因为内部函数innerDiameter并不会继承外部函数outerDiameter的this值。outerDiameter函数的this值对应circle对象,故this.radius等于10。
然而,innerDiameter函数的this值并非circle对象,那它究竟指向何处?它是innerDiameter函数执行时的当前context object,该context object又是什么?对此我也感到困惑,因此不妨进行实测:
// innerDiameter函数中的this是window
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = function() {
console.log(this === window);
};
innerDiameter();
}
};
circle.outerDiameter(); // 打印true
innerDiameter函数中的this指向window,具体原因暂且不究,关键在于它并非circle对象。
因此,若直接在innerDiameter函数中使用this,将会导致问题:
// 使用普通函数
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = function() {
console.log(2 * this.radius);
};
innerDiameter();
}
};
circle.outerDiameter(); // 打印NaN
鉴于此,我们不得不借助临时变量self,将外部函数outerDiameter的this值传递至内部函数innerDiameter。
.bind(this)
我们也可以利用.bind(this)来规避this值动态变化的问题:
// 使用.bind(this)
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = function() {
console.log(2 * this.radius);
};
innerDiameter = innerDiameter.bind(this);
innerDiameter();
}
};
circle.outerDiameter(); // 打印20
然而,无论是采用临时变量self,还是使用.bind(this),均非最为简洁的方案。
综上所述,常规函数的this取值机制略显怪异,尤其在采用面向对象编程时,频繁涉及this的使用,多数情况下我们不会选择.bind(this),而是倾向于使用临时变量self或that来传递this值,这种写法不仅繁琐,且极易引入BUG。
正如MDN文档所指出:
Until arrow functions, every new function defined its own this value based on how the function was called。This proved to be less than ideal with an object-oriented style of programming.
箭头函数简化this取值
箭头函数
箭头函数的this取值规则极为简单,因为在箭头函数中,this可视为一个普通变量。
An arrow function does not have its own this. The this value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules.
箭头函数不具备自身的this值,其内部引用的this均源自函数作用域链,其取值遵循与普通变量相同的规则,即在函数作用域链中逐层向上查找。
借助箭头函数,只要遵循以下规则,this的问题基本得以解决:
- 对于需通过object.method()方式调用的函数,应采用常规函数定义,避免使用箭头函数。对象方法中使用的this值具有明确含义,特指object本身。
- 其余所有情形,一律采用箭头函数。
// 使用箭头函数
var circle = {
radius: 10,
outerDiameter() {
var innerDiameter = () => {
console.log(2 * this.radius);
};
innerDiameter();
}
};
circle.outerDiameter(); // 打印20
对于内部函数innerDiameter,其自身并无this值,其所使用的this源自作用域链,即更高层函数的作用域。innerDiameter的外层函数outerDiameter为常规函数,具备this值,其this值即为circle对象。因此,innerDiameter函数中所使用的this源自outerDiameter函数,其值为circle对象。
结论与建议
总结
JavaScript由Brendan Eich耗时10天设计而成,因此存在诸多令人费解的特性,this便是其中之一。值得庆幸的是,近年来ECMAScript标准演进迅速且稳定,每年发布新标准,一定程度上弥补了JS的先天缺陷。
箭头函数对this取值规则的简化,旨在减少开发者的困扰,毕竟常规函数this取值的诸多限制难以记忆……
另外,MDN文档堪称宝库,建议多加查阅。
以上即为本文全部内容,期望对各位的学习有所助益,也恳请大家继续支持本站。
什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
