this 绑定解析

182 阅读3分钟

1.this 一般绑定

在全局执行上下文中,this 指向 全局的window对象。在函数执行上下文中,this的值取决于该函数的调用方式,若是通过被一个引用对象调用,那么 this 会被设置成那个对象,否则,this 绑定在 全局 window 对象上或是 undefined(严格模式上)
    let foo = {
        a: 'foo',
        bar: function() {
            console.log(this, this.a)
        }
    }

    foo.bar(); // 指向 foo,a==foo
    var a = 'window';
    let bar = foo.bar;
    bar(); // 指向 window ,a==window,若对a 的定义,使用let,则this.a为undefined,因为 let 定义变量不会绑定全局作用域


2.使用箭头函数改变 this 的绑定 

请大家考虑:

var a='window';
let foo={
	a:'foo',
	bar:()=>{
	    console.log(this,this.a)
	}
}
foo.bar()
// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …} "window"

尽管我们以 foo.bar( ) 的形式调用,this.a 依旧不是指向 foo 这个对象。this 指向 wondow 的原因是,它是从包围的作用域中词法继承而来的 this 。(换句话说,就是箭头函数的 this 指向当前作用域的父级作用域)

注:箭头函数实现原理看下面第四点~

3.其他常见 this 修改绑定

  • call : fn.call(targetObj,a,b ...)

targetObj 表示绑定的对象,a , b ... 表示调用函数 fn 的参数,参数展开写就可以

var fn={
	a:'fn',
	make:function(m,n) {console.log(this.a,m+n)}
}
var bar={
	a:'bar'
}
fn.make.call(bar)
// bar 3

  • apply : fn.apply(targetObj,[a,b,...])

targetObj 表示绑定的对象,a , b ... 表示调用函数 fn 的参数,参数存放在数组

var fn={
	a:'fn',
	make:function(m,n) {console.log(this.a,m+n)}
}
var bar={
	a:'bar'
}
fn.make.apply(bar,[1,2])
// bar 3

  • bind : fn.bind(targetObj , a ,b ... )()

targetObj 表示绑定的对象,a,b ... 表示调用函数的参数,参数展开书写即可。bind 区别于 call 和 apply ,bind 返回的是函数,需要调用才会执行

var fn={
	a:'fn',
	make:function(m,n) {console.log(this.a,m+n)}
}
var bar={
	a:'bar'
}
fn.make.bind(bar,1,2)()
// bar 3

4.箭头函数实现原理补充

箭头函数的主要设计目的就是以特定的方式改变 this 的行为特征。

接下来我们来观察它是如何实现的,请看以下代码:

var controller = {
      make:function(...) {
          btn.addEventListener ("click",function(){
                this.make();
        },false)
      }
}

以上代码运行时是会报语法错误的。错误的原因即是:this 绑定是动态性的,代码中的 this 和make()本身的this绑定是不同的,所以会造成错误。

以下是上面代码的正确写法,使用 var self = this 这一hack(变量 self 依赖于词法作用域的可预测性)

ar controller = {
      make:function(...) {
          var self = this;
          btn.addEventListener ("click",function(){
                self.make();
        },false)
      }
}

在前面的代码中,如果使用箭头函数作为回调, this 则如我们所愿是可预测的。


考虑:

var controller = {
      make:function(...) {
          btn.addEventListener ("click",()=>{
                this.make();
        },false)
      }
}

前面代码的箭头函数回调中的词法 this 现在与封装函数 make()指向同样的值,也就是说,=> 是 var self = this 的词法替代形式


你的喜欢就是我写作的最大动力 ~

                                                     欢迎大家留言共同讨论 ~