携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
关于this
this 关键字是javascript中最复杂的机制之一。比如说:在React中我们经常会使用bind将函数绑定在类组件上,或者在JSX直接使用箭头函数调用方法。
当我们编写的方法需要传递对象作为参数时,我们可以使用this来隐式地传递这个对象引用,因此可以将API设计的更加简洁且便于复用。
当我们的设计越来越复杂的时候,显示传递上下文对象会让代码变得越来越混乱。但是隐式传递对象则不会这样。
在接下来让我们全面且详细地复习巩固一下this的绑定规则。
this的绑定
首先:this是在运行时绑定的,不是在编写时绑定的,它的上下文取决于函数调用时的各种条件。 this的绑定和函数的声明位置没有任何关系,只取决于函数的调用方式。
1. 默认绑定
function foo(){
console.log(this.a)
}
var a = 1
foo()
这里毫无疑问会输出:1
我们声明了一个变量a,这个a就是全局对象的一个属性,在浏览器中就等价与window.a = 1,当我们调用foo()时,this.a被解析成了window.a。
这里就发生了默认绑定,this指向了全局对象。
在代码中,foo()是直接使用不带任何修饰的函数引用进行调用的,因此只能是默认绑定。
2. 隐式绑定
function foo(){
console.log(this.a)
}
var obj = {
a: 2,
foo: foo
}
obj.foo()
首先我们需要明确foo的声明方式,obj中的foo属性只是引用了这个函数,这个函数并不属于obj对象。但是,调用位置会使用obj上下文引用函数,或者说函数被调用时obj对象拥有这个函数引用。
当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象上。
3. 显式绑定
隐式绑定需要我们在对象上有一个指向函数的属性,并通过这个属性间接调用函数,从而把函数的this隐式绑定到这个对象上。那我们怎么在某个对象上强制调用它不存在的函数呢。
这个时候我们可以使用call() 和apply()方法进行显示绑定。
function foo() {
console.log(this.a)
}
var obj = {
a:3
}
foo.call(obj)
4. new绑定
function foo(a) {
this.a = a
}
var bar = new foo(4)
console.log(bar.a)
最终将输出:4。
使用new来调用foo()的时候,我们会构造一个新对象并把它绑定到foo()调用中的this上。这就是new绑定。
this绑定优先级
如何判断一个运行中函数的this绑定, 需要找到函数的直接调用位置,之后按照下面顺序判断this的绑定对象
- 由
new调用:绑定到新创建的对象 - 由
call或apply或bind调用: 绑定到指定对象 - 由上下文对象调用:绑定到上下文对象
- 默认:在严格模式下绑定到
undefined, 否则绑定到全局对象