js中this的指向

之前学习js时发现this比较难懂,找了一些文章来看,现在自己尝试写一下,看看自己是否真的懂了。

就我自己所理解的,this值存在于函数里面,一般对象是没有的;this的指向有几个规则。1.默认绑定;2.隐式绑定;3.显示绑定;4.new 绑定;

this的指向只有在运行时才能确定而不是定义时;

它们的优先级是:4 > 3 > 2 > 1

箭头函数有点特殊,后面会说到;

1.默认绑定

    在没有其他规则下使用的就是默认绑定这个规则;一般指的是独立函数


      function fn() {
        console.log('默认绑定', this);

  默认绑定下this指向的全局对象(window)
      }

      fn();

   输出结果:

  

 如果是严格模式下this是指向undefined


    "use strict";  //严格模式

      function fn() {
        console.log('默认绑定', this);
      }

      fn();

  

 

2.隐式绑定

  一般是指某个对象的方法

  "use strict";

      var name = 'sky';

      function fn() {
        console.log('隐式绑定', this.name);
      }

      const obj = {
        name: 'blue',
        sayName: fn
      };

      obj.sayName();  // 这里的函数作为对象的方法this指向的是调用这个方法的对象,即obj

  输出结果:
  

 

  如果有多层对象的,只有最后一层对象才会影响this的指向;如:obj.p.sayName(); // 影响this指向的是p这个对象。

  var name = 'sky';

      function fn() {
        console.log('隐式绑定', this.name);
      }

      const pn = {
        name: 'red',
        sayName: fn,
      }

      const obj = {
        name: 'blue',
        p: pn,
      };

      obj.p.sayName();

 

有时会出现隐式绑定丢失;其实是被骗了,不存在所谓丢失

 

  var name = 'sky';

      function fn() {
        console.log('隐式绑定', this.name);
      }

      const obj = {
        name: 'blue',
        sayName: fn,
      };

     

      var sayName = obj.sayName;
      sayName();

  输出结果:

  

 

  this指向的全局变量,这个时候应用的默认绑定的规则,

  var sayName = obj.sayName; // obj.sayName是把方法赋值给了sayName这个变量,这时sayName不再是某个对象的方法,而是一个独立的函数;

  所以才说被骗;

  

3.显式绑定

  是通过call(); apply(), bind()来改变函数this的指向

  var name = 'sky';

      function fn() {
        console.log('显示绑定', this.name);
      }

      const obj = {
        name: 'blue',
        sayName: fn,
      };

     fn.apply(obj); // 手动把this指向到obj中, call()和apply()是改变的同时也调用了函数;bind()只是改变并没有调用,会返回一个改变后的函数;

  显示绑定也会出现丢失,但是我觉得不算是一种丢失

  var name = 'sky';

      function fn() {
        console.log('显示绑定', this.name);
      }

      const obj = {
        name: 'blue',
        sayName: fn,
      };

     

     var Hi = function(fn) {
       fn();
     }

     Hi.call(obj, fn);  // 搞不懂为什么这样也叫丢失,Hi函数就根本没有this,怎么改的了

 

4.new 绑定

 js不同其他的语言,任何一个函数都可以使用new来调用,因此不存在构造函数,而是对函数的“构造调用”;

 使用 new 来调用函数,会自动执行下面的操作

  1.创建一个新对象

  2.将构造函数的作用域赋值给新对象,即this指向这个新对象

  3.执行构造函数中的代码

  4.返回新对象

 

   所以用 new 来调用这个函数时this就会绑定到这个新对象中

   var name = 'sky';

     function sayHi(name) {
       this.name = name;
     }

     var t = new sayHi('tttt');
     console.log(t.name);

  输出结果: tttt

 

最后,说说箭头函数

  1. 箭头函数自己本身是没有this的,它是继承外层代码块的this(我认为指的就是函数,一般的对象是没有this的)

  2.不可以当作构造函数,所以不能使用new命令,不然会报错

  3.不可以使用 arguments 对象,该对象在函数体内不存在,如果要用,可以使用rest参数代替

  4.不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数

  5. 箭头函数没有自己的this,所以不能用call, apply, bind

 

   const obj = {
        hi: function() {
         console.log('普通函数', this)
         return () => { console.log('箭头函数', this) };
       },
     };

     var t = obj.hi();
     t();

  结果:

    

  结果显示了箭头函数的this是继承上一层代码块的this;

 

posted @ 2021-06-06 09:12  sky-su  阅读(106)  评论(0)    收藏  举报