你不知道的javascript--------(二)this

17 阅读2分钟

this绑定方式

1. 默认绑定
function foo(){
  console.log('this.a',this.a)
}
var a = 2
foo() //this.a 2

函数调用的时候应用了this的默认绑定,因此this指向了全局对象window。

2. 隐式绑定
function foo(){
  console.log('this.a',this.a)
}
var a = 2
var obj = {
  a:3,
  foo:foo
}
obj.foo() //this.a 3

当foo()被调用的时候,他的前面加上了对obj的引用。当函数引用有上下文对象的时候,隐式绑定会吧函数调用中的this绑定到这个上下文对象上。

隐式绑定存在的问题:

隐式丢失:隐式绑定的函数丢失绑定对象,也就是说他会使用默认绑定,从而把this绑定到全局对象或者undefined上,取决于是否是严格模式。

示例一:

function foo(){
  console.log('this.a',this.a)
}
var a = 2
var obj = {
  a:3,
  foo:foo
}
var bar = obj.foo
bar() //this.a 2

解析:虽然bar是对obj.foo的引用,但是实际上,它引用的是foo函数本身,因此此时的bar()是一个不带任何修饰的函数调用(相当于foo()),因此应用了默认绑定。

示例二:

function foo(){
  console.log('this.a',this.a)
}
function doFoo(fn){
  fn() //fn引用的实际上是foo
}
var a = 'global'
var obj = {
  a:'obj',
  foo:foo
}
doFoo(obj.foo) //this.a global

解析:参数传递实际上是隐式赋值,因此我们传递函数的时候也是一样的。传递参数中的obj.foo其实和示例一种的bar = obj.foo意义一样。

3.显式绑定

使用bind,call,apply改变this的指向问题。juejin.cn/post/711047…

4.new绑定

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

解析:在使用new 调用foo()的时候,我们会构造一个新对象并把它绑定到了foo()调用中的this上。

涉及知识点:在new的时候发生了什么。juejin.cn/post/710949…

5.被忽略的this

如果把null或者undefined作为this的绑定对象传入call,apply或者bind,这些值在调用的时候会被忽略掉,实际上使用的是默认绑定规则。

function foo(){
  console.log(this.a)
}
var a = 2
foo.call(null)

如果函数并不关心this的话,但是仍然需要传入一个值作为占位值,这个时候null是一个不错的选择。

6.箭头函数

箭头函数不适用this的几种绑定规则,而是根据外层的(函数或者全局)作用域来决定this

function foo(){
  return (a) => {
    console.log(this.a)
  }
}
var obj1 = {
  a:2
}
var obj2 = {
  a:3
}
var bar = foo.call(obj1)
bar(obj2) //2

解析:foo()内部创建的箭头函数会捕获调用时foo()的this,由于foo()的this绑定到obj1,bar(引用箭头函数)的this也会绑定到obj1,箭头函数的绑定无法被修改。