全面解析this

每个函数的this实在调用时被绑定的,完全取决于函数的调用位置。我们找到函数的调用位置,然后运用以下四种绑定规则来判断函数的this指向。
1、默认绑定

function foo (){
  console.log(this.a)
}
let a = 1
foo() // 1

函数的this会默认绑定到全局对象window上,如果在严格模式中,this绑定到undefined
2、隐式绑定
调用位置是否有上下文对象,或者被某个对象拥有或包含。

function foo(){
  console.log(this.a)
}
let obj = {
  a: 2,
  foo:foo
}
let a = 1
obj.foo(); //2
function foo(){
  console.log(this.a)
}
let obj1 = {
  a: 2,
  foo: foo
}
let obj2 = {
  a: 3,
  obj1: obj1
}
let a = 1
obj2.obj1.foo(); //2

3、显示绑定

function foo(){
  console.log(this.a)
}
let obj = {
  a: 1
}
foo.call(obj)

4、new绑定

function foo(a){
  this.a = a
}
let bar = new foo(2)
console.log(bar.a) // 2

理解以上四种绑定规则以后,我们再来看一下四种绑定规则的优先级,哪个优先级高this绑定的就是哪个。

优先级

默认绑定的优先级是最低的

1、显示绑定 pk 隐式绑定

function foo(){
  console.log(this.a)
}
let obj1 = {
  a: 1,
  foo: foo
}
let obj2 = {
  a:2
}
console.log(obj1.foo()) // 1
obj1.foo.call(obj2) // 2

通过以上代码我们可以看到显示绑定的优先级高于隐式绑定

显示绑定 pk new 绑定

function foo(a){
  this.a = a
}
let obj1 = {
    foo
}
let bar = foo.bind(obj1)
bar(2)
console.log(obj1.a) // 2

let bar2 = new bar(3)
console.log(obj1.a) // 2
console.log(bar2.a) // 3

new修改了显示绑定 调用bar中的this,所以new绑定的优先级高于显示绑定

结论

我们判断一个函数的this指向,可以按照下面的顺序来判断
1、函数是否在new中调用,如果是的话 this绑定的是新创建的对象

let bar = new foo()

2、函数是否通过call、apply、bind的方式调用,如果是的话 this绑定的是指定的对象

let obj1 = {}
let bar = foo.call(obj1)

3、函数是否在某个上下文中被调用,如果是的话 this绑定的是函数调用的上下文

function foo(){
}
let obj1 = {
  foo
}
let bar = obj1.foo()

4、除此之外 this绑定的就是全局对象 在严格模式下绑定的是undefined

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容