JavaScript中的this

JavaScript中的this,和面向对象语言中的this有些不同……

函数上下文

this指函数调用相关联的对象,称之为函数上下文。可以在函数内部获取到。

函数上下文是来自面向对象语言(如Java)的概念,在面向对象语言中,方法定义在类内部,因此需要一个机制来获取当前类的实例的一些信息,这就产生了thisthis通常指向定义当前方法的类的实例 。不过,在JavaScript中,函数并不和对象绑定,是可以单独调用的。除了作为一个方法(method)来调用,还有一些其他的调用方法。根据调用方法的不同,this的值也不同。也就是说,JavaScript中this的值是在调用时计算出来的。

调用函数的方法

函数的调用方法有以下几种:

  1. 作为一个函数(function),直接调用。
add(1, 2)
  1. 作为一个方法(method),关联在一个对象上,实现面向对象编程。
obj.add(1, 2)
  1. 作为构造函数,实例化一个新对象。
new Person()
  1. 通过call或者apply方法调用。可以指定this的值。

作为函数直接调用

作为函数直接调用,this的值可能为全局变量window(非严格模式下)或者undefined(严格模式下)。

作为方法被调用

let user = {
name: "John",
age: 30,

sayHi() {
// "this" 指的是“当前的对象”
console.log(this.name); // 等同于console.log(user.name)
}

};

user.sayHi(); // John

作为方法被调用时,this指向调用该方法的对象,也就是user

如果没有this关键字,那么,如果我们将user复制给另一个变量admin,sayHi方法需要改成这样:

sayHi() {
console.log(admin.name);
}

这样不利于代码复用。

作为构造函数

使用new关键字调用构造函数。

function User(name) {
this.name = name;
this.isAdmin = false;
}

let user = new User("Jack");

当一个函数被使用 new 操作符执行时,它按照以下步骤:

  1. 一个新的空对象被创建并分配给 this
  2. 函数体执行。通常它会修改 this,为其添加新的属性。
  3. 返回 this 的值。

换句话说,new User(...) 做的就是类似的事情:

function User(name) {
// this = {};(隐式创建)

// 添加属性到 this
this.name = name;
this.isAdmin = false;

// return this;(隐式返回)
}

构造函数中的this,始终指向这个新创建的对象。

注意,我们也可以显式给构造函数返回一个值。返回的值遵循以下规则:

  • 如果 return 返回的是一个对象,则返回这个对象,而不是 this
  • 如果 return 返回的是一个原始类型,则忽略。

通过call或者apply方法调用

我们可以通过call或者apply调用一个方法:

function fn() {
console.log(this)
console.log(arguments)
}
fn.call(1, 2, 3, 4) //第一个参数就会被当成this传进去

注意,如果传递的this不是对象,js会默认封装成对象:

fn.call(1) //这个1会变成一个对象

方法定义里加上一句'use strict'之后,这个1就不会变成对象了。

function fn() {
'use strict'
console.log(this)
}
fn.call(1) //这个1不会变成对象

apply方法也可以用来显式传递this,区别是apply后面传一整个参数数组,call传单个的参数。

fn.call(undefined, 1, 2)
fn.apply(undefined, [1,2])

bind方法,绑定this

bind方法会接收一个参数,返回一个新函数,bind的第一个参数就是新函数的this

function f1(p1, p2) {
console.log(this, p1, p2)
}
let f2 = f1.bind({name: 'xxx'})

f2就是f1绑定了this之后的新函数。

f2()等价于f1.call({name: 'xxx'})

.bind还可以绑定其他参数:

let f3 = f1.bind({name: 'xxx'}, 'hi')

f3()等价于f1.call({name: 'xxx'}, 'hi')

总结

JavaScript中函数不与一个对象绑定,可以单独调用,此外还可以通过callapply调用。

this是函数调用上下文对象,表示函数调用时的环境。

根据函数调用方式的不同,this的值也不同:

  • 单独调用时,this的值为undefined(严格模式)或者window(非严格模式)。

  • 作为对象的方法被调用时,值为调用该方法的对象。

  • 构造方法中,this指向一个隐形的空对象,构造函数对this进行操作之后会隐式return this。不过,也可以显式return一个值。

  • callapply方法可以显式指定this的值,区别是apply后面传一整个参数数组,call传单个的参数。

  • 函数调用bind方法,可以显式指定该函数的this的值,返回一个新函数,新函数的this就是我们给的值。

Author: kpt

Permalink: http://kpt.ink/2021/08/05/JavaScript%E4%B8%AD%E7%9A%84this/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。