深入理解 JavaScript 中的 "this" 关键字
- 在 JavaScript 中,关键字
this
是一个经常让人感到困惑的概念。它的指向并不总是显而易见,因为它取决于函数的调用方式。在本文中,我们将深入探讨this
的指向,以及不同情况下它的表现。
一、this的使用场景
-
全局中的 "this"
当在全局上下文中调用函数时,
this
指向的是全局对象。在浏览器中,这个全局对象通常是window
对象。在node
环境中,指向global
对象。(注意:node
环境中没有this
)浏览器:
node环境:
-
构造函数中的 "this"
构造函数中的this指向取决于函数的调用方式。
1、当函数作为构造函数调用(使用
new
关键字)时,this
指向新创建的对象。function Constructor() { this.name = "mhr"; console.log(this); } var newObj = new Constructor(); // this 指向新创建的对象 console.log(newObj.name); // mhr
2、函数被单独调用时,触发的是默认绑定规则,该函数的
this
指向window
。(注意:使用var
声明的变量为全局变量,即属于window
对象属性)var name = "windownName"; function fun() { var name = 'mhr'; console.log(this.name) } fun(); // windownName
3、当函数作为对象的方法调用时,
this
指向调用该方法的对象。函数被多个对象链式调用时,this
指向最近的那个对象。const obj = { name: 'obj.name', fun: function() { console.log(this.name) }, obj1: { name: 'obj.obj1.name', fun: function() { console.log(this.name); }, } } obj.fun(); // obj.name obj.obj1.fun(); // obj.obj1.name
-
箭头函数中的 "this"
在箭头函数中,
this
的指向与普通函数有所不同。在箭头函数中,this
的值是根据箭头函数所在的词法作用域来决定的,而不是动态改变的。具体来说,箭头函数没有自己的
this
值,它会捕获所在上下文的this
值。这意味着箭头函数内部的this
将指向箭头函数声明时所在的作用域的this
,而不是在调用时的this
。这种行为与普通函数不同,普通函数的
this
值是在运行时动态确定的,取决于函数的调用方式。而箭头函数的this
值是在定义时确定的,取决于箭头函数所在的上下文。var name = "windownName"; const obj = { name: 'obj.name', fun: () => { console.log(this.name) }, obj1: { name: 'obj.obj1.name', fun: () => { console.log(this.name) }, } } obj.fun(); // windownName(指向 window) obj.obj1.fun(); // windownName(指向 window)
二、改变this指向规则
在 JavaScript 中,call
、apply
和 bind
可以显式设置函数内部 this
值的方法。
1、call 方法:
语法:function.call(thisArg, arg1, arg2, ...)
call 方法允许你在调用函数的同时指定函数内部的 this 指向(thisArg),并且可以传入多个参数。第一个参数是要绑定给 this 的值,后续参数是传递给函数的参数列表。
function greet(name) {
console.log(`Hello, ${name}. I am ${this.title}`); // Hello, Smith. I am Mhr
}
const person = { title: 'Mhr' };
greet.call(person, 'Smith');
2、apply 方法:
语法:function.apply(thisArg, [argsArray])
apply 方法与 call 类似,但是它接受的参数是以数组的形式传入的。第一个参数是要绑定给 this 的值,第二个参数是一个数组,包含了传递给函数的参数列表。
举例:
function introduce(age, gender) {
console.log(`I am ${this.name}, ${age} years old, ${gender}.`); // I am Mhr, 26 years old, male.
}
const person = { name: 'Mhr' };
introduce.apply(person, [26, 'male']);
3、bind 方法:
语法:function.bind(thisArg, arg1, arg2, ...)
bind
方法会创建一个新的函数,其内部的 this
值被绑定到 bind
方法的第一个参数。bind
方法不会立即执行函数,而是返回一个绑定了指定 this
值的新函数,可以稍后调用。
举例:
function saySomething(message) {
console.log(`${this.name} says: ${message}`); // Mhr says: Hi
}
const person = { name: 'Mhr' };
const saySomethingForBob = saySomething.bind(person);
saySomethingForBob('Hi');
方法 | 参数类型 | 是否立即调用 | 备注 |
---|---|---|---|
call | arg1, arg2, ... | 是 | |
apply | [arg1, arg2, ...] | 是 | 方法开始字母为a ,可以想到Array , 所以参数是一个数组 |
bind | arg1, arg2, ... | 否 | 只是绑定,所以不会立即执行 |
小结:
call、apply都会立即执行,bind不会立即执行,只是返回一个新的函数。
call、bind参数一样,apply参数为一个数组
三、总结
1、普通函数中,this
的指向是动态确定的,取决于函数的调用方式。了解 this
的指向是理解 JavaScript 中关键概念的重要一步。通过本文的介绍,希望读者能够更清晰地理解 this
的工作原理,并在实际开发中更加灵活地运用它。
2、箭头函数没有自己的 this
值,它会捕获所在上下文的 this
值。这意味着箭头函数内部的 this
将指向箭头函数声明时所在的作用域的 this
,而不是在调用时的 this
。
3、call
、apply
和 bind
可以显式设置函数内部 this
的指向。
4、this
的概念虽然简单,但是在实际应用中可能会带来许多意想不到的困惑。通过不断的练习和实践,我们可以更好地掌握 this
的使用,从而写出更加清晰、可维护的 JavaScript 代码。
希望本文对读者有所帮助,让我们一起深入理解 JavaScript 中的 this
关键字,为我们的代码编写带来更多的便利和灵活性。
转载自:https://juejin.cn/post/7377794126098776104