JavaScript中的this
,和面向对象语言中的this
有些不同……
函数上下文
this
指函数调用相关联的对象,称之为函数上下文。可以在函数内部获取到。
函数上下文是来自面向对象语言(如Java)的概念,在面向对象语言中,方法定义在类内部,因此需要一个机制来获取当前类的实例的一些信息,这就产生了this
。this
通常指向定义当前方法的类的实例 。不过,在JavaScript中,函数并不和对象绑定,是可以单独调用的。除了作为一个方法(method)来调用,还有一些其他的调用方法。根据调用方法的不同,this
的值也不同。也就是说,JavaScript中this
的值是在调用时计算出来的。
调用函数的方法
函数的调用方法有以下几种:
- 作为一个函数(function),直接调用。
add(1, 2) |
- 作为一个方法(method),关联在一个对象上,实现面向对象编程。
obj.add(1, 2) |
- 作为构造函数,实例化一个新对象。
new Person() |
- 通过
call
或者apply
方法调用。可以指定this
的值。
作为函数直接调用
作为函数直接调用,this
的值可能为全局变量window
(非严格模式下)或者undefined
(严格模式下)。
作为方法被调用
let user = { |
作为方法被调用时,this
指向调用该方法的对象,也就是user
。
如果没有this
关键字,那么,如果我们将user复制给另一个变量admin,sayHi方法需要改成这样:
sayHi() { |
这样不利于代码复用。
作为构造函数
使用new
关键字调用构造函数。
function User(name) { |
当一个函数被使用 new
操作符执行时,它按照以下步骤:
- 一个新的空对象被创建并分配给
this
。 - 函数体执行。通常它会修改
this
,为其添加新的属性。 - 返回
this
的值。
换句话说,new User(...)
做的就是类似的事情:
function User(name) { |
构造函数中的this,始终指向这个新创建的对象。
注意,我们也可以显式给构造函数返回一个值。返回的值遵循以下规则:
- 如果
return
返回的是一个对象,则返回这个对象,而不是this
。 - 如果
return
返回的是一个原始类型,则忽略。
通过call或者apply方法调用
我们可以通过call
或者apply
调用一个方法:
function fn() { |
注意,如果传递的this
不是对象,js会默认封装成对象:
fn.call(1) //这个1会变成一个对象 |
方法定义里加上一句'use strict'
之后,这个1就不会变成对象了。
function fn() { |
apply
方法也可以用来显式传递this
,区别是apply
后面传一整个参数数组,call
传单个的参数。
fn.call(undefined, 1, 2) |
bind方法,绑定this
bind
方法会接收一个参数,返回一个新函数,bind
的第一个参数就是新函数的this
。
function f1(p1, p2) { |
f2
就是f1
绑定了this
之后的新函数。
f2()
等价于f1.call({name: 'xxx'})
。
.bind
还可以绑定其他参数:
let f3 = f1.bind({name: 'xxx'}, 'hi') |
f3()
等价于f1.call({name: 'xxx'}, 'hi')
。
总结
JavaScript中函数不与一个对象绑定,可以单独调用,此外还可以通过call
、apply
调用。
this
是函数调用上下文对象,表示函数调用时的环境。
根据函数调用方式的不同,this
的值也不同:
单独调用时,
this
的值为undefined
(严格模式)或者window
(非严格模式)。作为对象的方法被调用时,值为调用该方法的对象。
构造方法中,
this
指向一个隐形的空对象,构造函数对this
进行操作之后会隐式return this
。不过,也可以显式return
一个值。call
和apply
方法可以显式指定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 协议进行许可,使用时请注意遵守协议。