this的理解

记录一下自己关于this的理解

1.this的官方说法---参考JavaScript高级程序设计语言
this对象是在运行时基于函数的执行环境绑定的。也就是说,this代表的是函数执行时,所运行环境的主体对象。

2.this设计的目的--参考阮一峰日志
函数一经创建,会存在内存中,赋值给变量的是函数在内存中的地址。这样函数在各种环境中就是一个单独的值,可以在不同环境中执行。因此需要有一种机制,能够在函数体内部获得当前的运行环境,以便于获取当前环境中的数据(个人理解)。

3.this的指向(个人理解)
我们所说的this指向,也就是this代表谁,绑定给了谁。我所理解地就是,this代表了函数被调用时,调用这个函数的对象,就是点前面的那个对象。
例如:window.fn() obj.fn(),前者是函数正常调用时,指向了window这个对象,后者是方法调用时,指向了这个调用方法的obj对象,它们都是点前面的对象。当然这只是一般情况下而言。

4.this的调用模式
我们都知道,this在函数刚被定义的时候,是没有任何意义的,只有函数在执行时(被调用),才会绑定执行主体,即确定指向,那么就可以通过函数的调用模式来确定this是如何确定指向的。

①函数调用模式,即普通的函数调用,this指向window

  var name = "bobo"
  function global(){
  var name = "lele"
   console.log(this.name)
  }
  global(); // "bobo" this指向window,thi.name就是window.name

  只要是函数单独调用,前面没有点的,都是函数调用模式,this指向window.例如:

  var name = "bobo"
  var obj = {
    name: 'lele',
    say: function () {
      console.log('hi,' + this.name);
    },
  };
  obj.say(); // hi,lele
  var sayHi = obj.say;
  sayHi(); // hi,bobo,sayHi被赋值了say方法的函数地址,本身已经是一个独立的函数,在执行时跟定义在全局中的函数一样,都是被window调用

②方法调用模式,即定义在对像中的方法是一个函数,当方法被调用时,就是该函数被调用

在上面的例子中已经写了,调用obj对象中的say方法时,方法中的this指向的是obj这个对象,所以this.name相当于是obj.name,结果是hi,lele
但是,方法调用模式中,我们常常迷惑的不是这么简单的调用,而是当出现多层调用时,this到底指向的是哪一层的调用对象,例如:

  var obj = {
    name: 'bobo',
    first: {
      name: 'lele',
      second: {
        name: 'mingming',
        say: function () {
          console.log('hi,' + this.name);
        },
      },
    },
  };
  obj.first.second.say(); // hi,mingming  this指向了second

  由此可见,this最终指向的是最后调用它的那一级对象,这里我用自己的理解方式,this指向的就是最终找到它的那个对象。

③构造函数调用模式

构造函数中的this,是由于new的作用,将this指向了它创建的实例对象

  function Person() {
    this.name = 'bobo';
    this.age = '23';
    this.say = function () {
      console.log('hi,bobo');
    };
  }
  var p = new Person();
  console.log(p.name); // bobo

这个应该比较容易理解,因为new已经帮我们确定好了this到底绑定给了谁,那就是new创造的实例对象。

④apply,call,bind方法调用,又叫做上下文调用

apply,call,bind是函数的方法,函数调用该方法之后,通过传参可以改变函数内部的this指向。

  var bobo = {
    hobby: '滑板',
    say: function () {
      console.log('我喜欢' + this.hobby);
    },
  };
  var lele = {
    hobby: '唱歌',
  };
  bobo.say(); // 我喜欢滑板
  bobo.say.apply(lele);// 我喜欢唱歌
  bobo.say.call(lele);// 我喜欢唱歌
  var leleSay = bobo.say.bind(lele); 
  leleSay();// 我喜欢唱歌

这三种方法都可以改变函数内部的this指向,但是又有所不同,这里对它们的区别暂时不做讨论。
这种方法我觉得应该叫做借用模式,就是通过改变this指向,使this指向的这个对象借用到这个方法,从而来获取该对象内的数据。

⑤特殊情况下的this指向

例如:事件函数内的this指向的是事件源,setTimeout setInterval 指向的是window,匿名函数的自调用(立即执行函数)指向window。
另外:在严格模式下,没有显示函数的调用主体时,即在函数调用模式下,不再指向window,而是指向undefined。

⑥箭头函数里面的this指向

箭头函数里面没有定义this,因此箭头函数里面写有this时,就会按照作用域链去查找有定义this的那一级作用域的this,这时的this就指向调用这个作用域函数的调用者。

  var id = 3;
  function foo() {
    var id = 2;
    // var that = this;
    //var this
    setTimeout(() => {
      console.log('id:', this.id);
    }, 100);
  }
  foo(); // id=2; 箭头函数没有定义this,所以this应该时foo函数中的this,而foo是window调用的,因此this指向window

  var obj = {
    id: 4,
    time: function () {
      var id = 5;
      var aa = {
        bb: () => {
          console.log('id:', this.id);
        },
      };
      aa.bb();
    },
  };
   obj.time(); // id=4,这时的this按照作用域查找,是time方法中的this,time方法被obj调用,this就指向obj

总结目前到这里,有新的发现,或者发现理解上的错误,再来修改。加油!

原文地址:https://www.cnblogs.com/mandymm/p/13955746.html