JS中的this对象

this对象表示函数的上下文对象,是函数运行时基于运行环境绑定的,this的值取决于函数是如何调用的,而不是如何定义的。函数的上下文,这是一个广泛的概念,涵盖了函数执行时的整个环境和状态,包括this对象、函数作用域、参数、调用战的信息、闭包状态等等,函数的上下文对象就是this。

作为函数被调用

1
function getName(name){ return this;}  

作为一个函数调用时,this对象指向window。

作为方法被调用

1
2
3
4
5
6
var obj = {
name:'hailee',
getName: function(){
return this;
}
}

作为一个方法调用时,this指向这个对象obj

作为构造函数被调用

1
2
3
4
5
6
function CreateToys(){
this.getName = function(){return this;}
}
var bear = new CreateToys()
bear.getName();
console.log(bear.getName()==bear) //true

当调用构造函数时会发生一系列特殊的操作,使用new关键字调用函数会触发下面3个动作:

  1. 创建一个新的空对象
  2. 该对象作为this参数传递给构造函数,从而成为构造函数的函数上下文对象
  3. 新构造出来的对象作为new运算符的返回值

构造函数与普通函数的区别

跟普通函数一样,构造函数可以被“正常”调用,或者作为对象的方法被调用,但是这样是没有意义的。构造函数的目的是根据初始条件对函数调用所创建的对象进行初始化,所以只有作为构造函数的时候才会有意义。因此出现了命名约定来区分普通函数跟构造函数。

使用call跟apply方法调用

每个函数上都存在call和apply方法,这是JS提供的一种调用函数的方式,从而可以指定任何对象作为函数执行的上下文对象,它们的参数分别为apply(this参数对象,参数数组),bind(this参数对象,参数列表)

1
2
3
4
5
6
7
8
9
10
11
function getScore(){
let score = 0
for(let i = 0;i < arguments.length;i++){
score += arguments[i];
}
this.score = score;
}
var obj1 = {}
var obj2 = {}
getScore.call(obj1,1,2,3,4) //this为obj1
getScore.apply(obj2,[1,2,3,4,5]) //this为obj2

解决函数上下文的问题

函数上下文与预期不符的时候,可以使用call和apply方法绕过,但是还有两种更优雅的方式。箭头函数跟bind()方法。

使用箭头函数

箭头函数跟普通函数有哪些区别?

  1. 箭头函数语法更简洁,单个表达式的情况可以省略花括号跟“return”关键字

  2. 箭头函数不绑定自己的“this”,而是继承它所在上下文的“this”值,普通函数有自己的“this”的绑定

  3. 箭头函数不能作为构造函数,不能使用new关键字,因为它没有自己的this对象和property属性

  4. 箭头函数没有自己的arguments对象

1
<button id="test">Click me!</button>
1
2
3
4
5
6
7
8
9
10
function Button(){
this.clicked = false;
this.click = ()=>{
console.log(clicked,'clicked')
this.clicked = true;
}
}
var button = new Button();
var ele = document.getElementById('test');
ele.addEventListener('click',button.click)

使用bind方法

1
<div class="title" id="test">Frank Running Club</div>
1
2
3
4
5
6
7
8
9
10
11
12
var button = {
clicked: false,
click: function(){
this.clicked = true;
console..log(this) // <div class="title" id="test">Frank Running Club</div>
}
}
var ele = document.getElementById('test');
ele.addEventListener('click',button.click);
//改进
ele.addEventListener('click',button.click.bind(button));

总结

this对象在开发的过程中是比较常用的,我们需要弄清楚在不同的使用场景下this对象到底是谁。

  1. 全局上下文:在全局函数中或不在任何对象内部定义的函数中,this 引用全局对象。在浏览器中,全局对象通常是 window
  2. 对象方法:当函数作为对象的方法被调用时,this 引用那个对象。
  3. 构造函数:在使用 new 关键字调用构造函数时,this 引用新创建的对象。
  4. DOM 事件处理器:在 DOM 事件处理函数中,this 通常引用触发事件的元素。
  5. 箭头函数:箭头函数不绑定自己的 this,而是继承它们的上下文绑定(即定义它们的上下文中的 this)。
  6. **使用 apply, call, bind**:这些方法可以显式地设置函数调用的上下文,即可以显式指定 this 的值