你不知道的this指向

1、this究竟是什么

  • 学习this的第一步是明白this既不指向函数自身也不指向函数的词法做用域,this其实是在函数被调用时发生的绑定,它指向什么彻底取决于函数在哪里被调用。

2、this的四种绑定规则

  • 默认绑定

    默认绑定通常发生在回调函数,函数直接调用;bash

    function fn() {
        console.log( this.a )
    }
    let a = 2;
    fn(); //2
    复制代码

    this.a被解析成了全局变量a,函数调用时应用了this的默认绑定,所以this指向全局对象。在代码中,fn是直接使用不带任何修饰的函数引用进行调用的,所以只能使用默认绑定,没法应用其余规则。app

    若是使用严格模式(use strict),则不能将全局对象用于默认绑定,所以this会绑定到undefined函数

  • 隐式绑定

    通俗来讲谁最终调用函数,this指向谁学习

    const obj = {
        name : 'lyq',
        getName () {
            console.log( this ); //obj
            console.log( this.name ); //lyq
        }
    };
    obj.getName();
    复制代码

    链式调用只有最后一层在调用位置中起做用ui

    var obj2 = {
        name:'lyq',
        foo() {
            console.log( this.name )
        }
    }
    var obj1 = {
        name:'zs',
        obj2:obj2
    }
    
    obj1.obj2.foo(); // lyq
    复制代码
    隐式丢失:

    一个最多见的this绑定问题是被隐式绑定的函数会丢失绑定对象,也就是你说它会应用默认绑定,从而把this绑定到全局对象或者undefined上,取决因而否是严格模式this

    var a = 100;
    
    var obj = {
        a : 2,
        foo() {
            console.log( this.a )
        }
    } 
    
    var bar = obj.foo;
    
    bar(); //100
    复制代码

    obj.foo 是引用属性,赋值给bar的实际上就是foo函数(即:bar指向foo自己,所以应用了默认绑定,指向全局属性aspa

  • 显示绑定call,apply,bind

    相对隐式绑定,this值在调用过程当中会动态变化,但是咱们就想绑定指定的对象,这时就用到了显示绑定。prototype

    显示绑定主要是经过改变对象的prototype关联对象。具体使用上,能够经过这两个方法call(…)或apply(…)来实现(大多数函数及本身建立的函数默认都提供这两个方法)。code

    function foo() {
        console.log( this.a )
    }
    
    var obj = {
        a : 2
    }
    
    foo.call( obj ) // 2
    
    复制代码

    call和bind是同样的,区别在于参数的设置上。对象

    硬绑定
    function foo() { 
        console.log( this.a );
    }
    
    var a = 2;
    
    var obj1 = { 
        a: 3,
    };
    
    var obj2 = { 
        a: 4,
    };
    
    var bar = function() {
      foo.call( obj1 );
    }
    
    setTimeout( bar, 100 ); // 3
    
    bar.call( obj2 );  //3
    
    复制代码

    这里须要注意下,虽然bar被显示绑定到obj2上,对于函数bar 中的this确实被绑定到了obj2,而foo由于经过foo.call( obj1 )已经显示绑定了obj1,因此在foo函数内,this指向的是obj1,不会由于bar函数内指向obj2而改变自身。因此打印的是obj1.a(即3)。

  • new绑定

    function foo(a) { 
        this.a = a;
    }
    
    var a = 2;
    
    var bar1 = new foo(3);
    console.log(bar1.a); // 3
    
    复制代码

    使用new来调用foo()时,会创造一个新对象并把它绑定到foo()调用中的this上。

    3、箭头函数this指向

    首先须要明确,箭头函数不适用以上this的四种标准规则,而是根据外层(函数或者全局)做用域来决定this

    箭头函数this的定义:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定 。

    var name = 'lyq';
    var obj = {
      name : 'zs',
      getName:function() {
        console.log( this.name )
      }
    }
    obj.getName(); //zs
    
    复制代码
    var name = 'lyq';
    var obj = {
      name : 'zs',
      getName:()=>{
        console.log( this.name )
      }
    }
    obj.getName(); //lyq
    复制代码

    所谓的定义时候绑定,就是this是继承自父执行上下文中的this,好比这里的箭头函数中的this.name,箭头函数自己所在的对象为obj,而obj的父执行上下文就是window,所以这里的this.name 实际上表示的是window.name,所以输出的是lyq。(this只有在函数被调用,或者经过构造函数new Object()的形式才会有this)

    注意简单对象(非函数)是没有执行上下文的!

    在setInterval和setTimeout中传入函数时,函数中的this会指向window对象。箭头函数可让setTimeout里面的this,绑定定义时所在的做用域,而不是指向运行时所在的做用域。

    export default {
      data () {
        return {
          name: zs,
        }
      },
      methods: {
        setName () {
          setTimeout(() => {
            this.name = 0;
          }, 500);
        }
      }
    }
    
    复制代码

    此时函数的this指向的是定义它的时候的对象,也就是this指向了data内中对应的变量。若是使用function,this则会指向window,没法得到当前对象。

相关文章
相关标签/搜索