• javascript的this指向问题深度解析


    参考来源[https://segmentfault.com/a/1190000008400124]

    1. javascript函数中的this指向并不是函数定义的时候确定的,而是在调用的时候确定的。相当于,函数的调用方式决定了this指向。

    2. js中普通函数的调用有三种方试:

      • 直接调用

      • 方法调用

      • new调用

      • 除外,还有些比如通过bind()将函数绑定到对象之后再调用、通过call()、apply()进行调用等。

    3. 直接调用的this指向问题

      • 就是直接通过函数名这种方式调用。这时候的函数内部的this指向全局对象,在浏览器中全局对象是window,在nodejs中全局对象是global。

      • 需要注意的是,直接调用并不是指在全局作用域下调用,在任何作用域下,直接通过函数名()来对函数进行调用的方式,都是直接调用。

      • bind()对直接调用的影响

      • function.prototype.bind()的作用是将当前函数与指定的对象绑定,并返回一个新函数,这个新函数无论以什么样的方式调用,其this始终指向绑定的对象。

      var obj = {};
      function test() {
          console.log(this===obj);
      }
      var testObj = test.bind(obj);
      test(); //false
      testObj(); //true
      
      
      • call()和apply()对this的影响

        1. function.prototype.apply()与function.prototype.call(),他们的第一个参数都是指定函数运行时其中的this指向。

        2. 不过使用aplly和call的时候,要注意,如果目录函数本身就是一个绑定了this对象的函数,那apply和call不会像预期的那样执行(所以慎用bind())。

            const obj = {};
        
            function test() {
                console.log(this === obj);
            }
            
            // 绑定到一个新对象,而不是 obj
            const testObj = test.bind({});
            test.apply(obj);    // true
            
            // 期望 this 是 obj,即输出 true
            // 但是因为 testObj 绑定了不是 obj 的对象,所以会输出 false
            testObj.apply(obj); // false
            
        
    4. 方法调用

      • 方法调用是指通过对象来调用其方法函数,它是对象.方法函数()这样的调用形式。这种情况下,函数中的this指向调用该方法的对象。但是,同样需要注意bind()的影响。
          const obj = {
              // 第一种方式,定义对象的时候定义其方法
              test() {
                  console.log(this === obj);
              }
          };
          
          // 第二种方式,对象定义好之后为其附加一个方法(函数表达式)
          obj.test2 = function() {
              console.log(this === obj);
          };
          
          // 第三种方式和第二种方式原理相同
          // 是对象定义好之后为其附加一个方法(函数定义)
          function t() {
              console.log(this === obj);
          }
          obj.test3 = t;
          
          // 这也是为对象附加一个方法函数
          // 但是这个函数绑定了一个不是 obj 的其它对象
          obj.test4 = (function() {
              console.log(this === obj);
          }).bind({});
          
          obj.test();     // true
          obj.test2();    // true
          obj.test3();    // true
          
          // 受 bind() 影响,test4 中的 this 指向不是 obj
          obj.test4();    // false
          
      
    5. 方法中this指向全局对象的情况

      • 这里说的方法中而不是方法调用中。方法中的this指向全局对象,如果不是因为bind(),那就一定不是用的方法调用方式,如下:
          const obj = {
              test() {
                  console.log(this === obj);
              }
          };
          
          const t = obj.test;
          t();    // false
      
      • t 就是 obj 的 test 方法,但是 t() 调用时,其中的 this 指向了全局。

      • 提出上面的情况就是为了防止,在将一个对象方法作为回调传递给某个函数之后,却发现运行结果和想的完全不一样的情况发生(忽略了调用方式对this的影响),如下:

      
          class Handlers {
          // 这里 $button 假设是一个指向某个按钮的 jQuery 对象
          constructor(data, $button) {
              this.data = data;
              $button.on("click", this.onButtonClick);
          }
          
          onButtonClick(e) {
              console.log(this.data);
          }
          }
          
          const handlers = new Handlers("string data", $("#someButton"));
          // 对 #someButton 进行点击操作之后
          // 输出 undefined
          // 但预期是输出 string data
          
      
      • this.onButtonClick作为参数传入on()之后,事件触发时,是对函数的直接调用,而不是方法调用,所以其中的this会指向window全局对象
    6. new调用

      • 在es5中,用new调用一个构造函数,会创建一个新对象,而其中的this就指向的这个新对象。
          var data = "Hi";    // 全局变量
          
          function AClass(data) {
          this.data = data;
          }
          
          var a = new AClass("Hello World");
          console.log(a.data);    // Hello World
          console.log(data);      // Hi
          
          var b = new AClass("Hello World");
          console.log(a === b);   // false
          
      
  • 相关阅读:
    System.IO.MemoryStream.cs
    System.IO.Stream.cs
    System.Web.HttpContext.cs
    System.Text.Encoding.cs
    System.Web.HttpRuntime.cs
    System.Web.Caching.Cache.cs
    System.Diagnostics.Stopwatch.cs
    FrameBuffer
    Java实现 洛谷 P1422 小玉家的电费
    Java实现 洛谷 P1422 小玉家的电费
  • 原文地址:https://www.cnblogs.com/minb/p/6437370.html
Copyright © 2020-2023  润新知