• JavaScript中this指针指向的彻底理解


    现在我们就来总结一下js中this的指向。首先需要了解一下几个概念:

    1、全局变量默认挂载在window对象下

    2、一般情况下this指向它的调用者

    3、es6的箭头函数中,this指向创建者,并非调用者

    4、通过call、apply、bind可以改改变this的指向

    在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等。

    下面我们具体分析一下

    1、在函数调用时

    //非严格模式下
    const func = function () {
        console.log(this);
        const func2 = function () {
          console.log(this);
        };
        func2(); //Window
      };
      func(); //Window
    
    //严格模式下
    
    'use strict'
      const func = function () {
        console.log(this);
        const func2 = function () {
          console.log(this);
        };
        func2(); //undefined
      };
      func(); //undefined

    2、作为对象方法

    const user = {
     
        userName: '小张',
        age: 18,
        selfIntroduction: function () {
          const str = '我的名字是:' + this.userName + ",年龄是:" + this.age;
        console.log(this);//user console.log(str); const loop
    = function () {
         console.log(this); //Window console.log(
    '我的名字是:' + this.userName + ",年龄是:" + this.age); }; loop(); //我的名字是:undefined,年龄是:undefined } }; user.selfIntroduction(); //我的名字是:小张,年龄是:18

    按照第二条规则,this指向他的调用者,selfIntroduction()方法的调用者是user,所以在selfIntroduction()方法内部this指向了他的父对象即user,而loop方法输出的为undefined的原因就是我在上面所说的javascript的设计缺陷了,在这种情况下,我们通常选择在selfIntroduction()方法里将this缓存下来。

    const user = {
        userName: '小张',
        age: 18,
        selfIntroduction: function () {
          const str = '我的名字是:' + this.userName + ",年龄是:" + this.age;
          console.log(str);
     
          const that=this;
     
          const loop = function () {
            console.log('我的名字是:' + that.userName + ",年龄是:" + that.age);
          };
     
          loop();   //我的名字是:小张,年龄是:18
     
        }
      };
     
      user.selfIntroduction();  //我的名字是:小张,年龄是:18

    此时loop的this指向就理想了。

    const user={
     
        userName:'小张',
        age:18,
        selfIntroduction:function(){
          const str='我的名字是:'+this.userName+",年龄是:"+this.age;
          console.log(str); 
        }
      };
     
      const other =user.selfIntroduction;
      other(); //我的名字是:undefined,年龄是:undefined
     
      const data={
        userName:'小李',
        age:19,
      };
      data.selfIntroduction=user.selfIntroduction;
      data.selfIntroduction(); //我的名字是:小李,年龄是:19

    在看这段代码,将selfIntroduction()赋值给了全局变量other,调用other()方法,other挂载在全局函数window对象下,window对象下没有userName 和 age 这两个属性,所以输出为undefined。

    第二段代码,申明了data对象,包含了username和age属性,记住我们的第二条规则一般情况下this指向它的调用者,大家就明白了,data是selfIntroduction()的函数的调用者,所以输出了data的userName和age。

    3:在html里作为事件触发

    <body>
      <div id="btn">点击我</div>
    </body>
         const btn=document.getElementById('btn');
        btn.addEventListener('click',function () {
          console.log(this); //<div id="btn">点击我</div>
        })

    在种情况其实也是遵循了第二条规则一般情况下this指向它的调用者,this指向了事件的事件源即event。

    4:new关键字(构造函数)

    构造函数中的this与被创建的新对象绑定。

    注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。

    const fun=function(userName){
        this.userName=userName;
      }
      const user=new fun('郭德纲');  
      console.log(user.userName); //郭德纲
    function C(){
      this.a = 37;
    }
    
    var o = new C();
    console.log(o.a); // logs 37
    
    
    function C2(){
      this.a = 37;
      return {a:38};
    }
    
    var b = new C2();
    console.log(b.a); // logs 38

    5:es6(箭头函数)

    const func1=()=>{
        console.log(this); 
      };
      func1(); //Window
    const data={
        userName:'校长',
        selfIntroduction:function(){
          console.log(this); //Object {userName: "校长", selfIntroduction: function}
          const func2=()=>{
            console.log(this); //Object {userName: "校长", selfIntroduction: function}
          }
     
          func2();
        }
      }
      data.selfIntroduction();

    大家在看看我开头说的第三条准则:es6的箭头函数中,this指向创建者,并非调用者,fun1 在全局函数下创建,所以this指向全局window,而fun2在对象data下创建,this指向data对象,所以在func2函数内部this指向data对象,个人认为es6的箭头函数的this指向是对我上面所说的javascript设计缺陷的改进,(个人认知)。

    6:改变this的指向

    当函数通过Function对象的原型中继承的方法 call() 和 apply() 方法调用时, 其函数内部的this值可绑定到 call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,JavaScript内部会尝试将其转换成对象然后指向它。

    function add(c, d){
      return this.a + this.b + c + d;
    }
    
    var o = {a:1, b:3};
    
    add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
    
    add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
    
    function tt() {
      console.log(this);
    }
    // 返回对象见下图(图1)
    tt.call(5);  // Number {[[PrimitiveValue]]: 5} 
    tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}

    而bind方法会返回一个可执行的函数。

    function f(){
      return this.a;
    }
    
    var g = f.bind({a:"azerty"});
    console.log(g()); // azerty
    
    var o = {a:37, f:f, g:g};
    console.log(o.f(), o.g()); // 37, azerty
  • 相关阅读:
    复制过来的东西也不靠谱,微信公众号第三方平台的API
    微信的加解密
    郁闷的错误
    Jquery Table 操作
    Html获取经纬度
    Mvc5 Html.EditorFor
    MVC5 烂笔头
    第三方应用开发的一点心得
    Socket 简易静态服务器 WPF MVVM模式(三)
    Socket 简易静态服务器 WPF MVVM模式(二)
  • 原文地址:https://www.cnblogs.com/fanmiaolan/p/9887539.html
Copyright © 2020-2023  润新知