JS底层知识中的this:掌握函数执行上下文的艺术
在JavaScript的世界里,this
关键字扮演着至关重要的角色,它决定了函数执行时的上下文环境。从基础的默认和隐式绑定,到复杂的显示绑定和箭头函数特性,this
的行为随着函数调用的方式而变化,深刻影响着代码的行为和逻辑。理解 this
的工作方式对于编写高质量、可维护的代码至关重要。本文将深入探讨 this
的概念、不同场景下的行为以及如何控制其绑定。
1. this
的基本概念
this
是一个特殊的关键字,在函数内部使用时,它引用的是函数执行时的上下文对象。this
指向的具体值取决于函数是如何被调用的。为了让对象中的函数有能力访问对象中的自己的属性,this可以显著的提升代码质量,减少上下文参数的传递
2. this
的指向规则
-
默认绑定:当函数作为普通函数调用时(不作为任何对象的方法),也就是当一个函数独立调用时,不带任何修饰符的调用,
this
指向全局对象(在浏览器中是window
)。但在严格模式下(use strict
),this
将是undefined
。function foo() { console.log(this); } foo(); // 在非严格模式下输出 window 对象,在严格模式下输出 undefined
-
隐式绑定:当一个函数被某个对象所拥有,或者函数被某个上下文对象调用时,该函数中的
this
指向该上下文对象var obj = { a: 1, foo: function () { console.log(this); // 输出 {a: 1, foo: [Function: foo]} } }; obj.foo();
-
隐式丢失:当一个函数被赋值给另一个变量再调用,那么
this
的绑定会丢失,导致默认绑定。 但是如果一个函数被多个对象链式调用时,this
会指向最近的那个对象。var obj = { a: 1, foo: function () { console.log(this.a); } }; var bar = obj.foo; bar(); // 输出 undefined (因为 `this` 变为全局对象)
-
显示绑定:通过
call
,apply
, 和bind
方法可以显式地设置函数调用时的this
值。将函数的this掰弯到一个对象中function foo(x, y) { console.log(this.a, x + y); } var obj = { a: 1 }; foo.call(obj, 1, 2); // 输出 1 3 foo.apply(obj,[1,2])//输出 1 3 const bar = foo.bind(obj,1,2);//bind 也可以 bar()
-
new绑定:使用
new
关键字调用函数时,this
指向新创建的对象实例。function Person() { this.name = '平平'; } let p = new Person(); console.log(p.name); // 输出 "平平"
3. 箭头函数中的 this
箭头函数没有自己的 this
绑定;它们继承自外层作用域的 this
。这意味着箭头函数内部的 this
通常与定义它的上下文有关,而不是调用它的上下文。
var obj = {
a: 1,
foo: function () {
const fn = () => {
console.log(this.a);
};
fn(); // 输出 1,这里的 `this` 是 `obj`
}
};
obj.foo();
手写 call
方法
为了更深入地理解 this
的绑定,我们可以通过手写 call
方法来模拟 JavaScript 内置的 call
功能。
Function.prototype.mycall = function (context) {
const context=arguments[0]
const args = Array.from(arguments).slice(1);
context.fn=this;
const res = context.fn(...args);
delete context.fn;
return res;
};
function foo() {
console.log(this.a);
}
var obj = { a: 1 };
foo.mycall(obj); // 输出 1
结尾
掌握 this
的行为对于JavaScript开发者来说是至关重要的,因为它直接影响着函数的执行上下文和数据的访问。掌握了this
的机制,开发者能够更加灵活地操纵函数,构建出更高效、更具可读性和可维护性的代码结构。无论是处理DOM事件、构造类方法还是实现闭包,对this
的理解都是必不可少的技能。
这次我们不仅探索了this
在不同场景下的表现,还亲手实现了简单的call
方法,加深了对this
绑定机制的理解。不过,理解this
并非一蹴而就的过程,而是需要不断实践和思考的旅程。继续加油吧
如果你对本文有任何疑问或见解,欢迎留言讨论。期待在前端开发的学习旅程中,与你一起加油!
转载自:https://juejin.cn/post/7389924114868781094