• JS中的This


    This的含义

    首先,this在构造函数中可以表示实例对象。

    function Person(name,gender){
          this.name = name;
          this.gender= gender;
    }
    

    而在其他地方,this则表示属性和方法当前所在的对象。this的值就是在点之前的这个对象,即调用该方法的对象。

    不管在什么场合,This总是返回一个对象!

    例子:方法中的this

    let user = {
      name: "John",
      age: 30,
    
      sayHi() {
        // "this" 指的是“当前的对象”
        alert(this.name);
      }
    };
    user.sayHi(); // John
    

    这里调用sayHi()的点之前的对象是user,因此this指向user。

    结论:以“方法”的语法调用函数时:object.method(),调用过程中的 this 值是 object。

    因为对象的属性可以赋值给另一个对象,所以this的指向也是可以改变的。

    var A = {
      name: '张三',
      describe: function () {
        return '姓名:'+ this.name;
      }
    };
    
    var B = {
      name: '李四'
    };
    
    B.describe = A.describe;
    B.describe() // "姓名:李四"
    

    B.describe的属性是从A得到的。此时B.describe中this的指向就指向了自己。B也就变成了这样:

    var B = {
      name: '李四'
      describe: function () {
        return '姓名:'+ this.name;
      }
    };
    

    上面的代码也可以这样写:

    function f() {
      return '姓名:'+ this.name;
    }
    
    var A = {
      name: '张三',
      describe: f
    };
    
    var B = {
      name: '李四',
      describe: f
    };
    
    A.describe() // "姓名:张三"
    B.describe() // "姓名:李四"
    // f中this的指向不同,结果不同。
    

    但是要注意的是,“复杂”调用中的this会失去目标。

    var obj ={
      foo: function () {
        console.log(this);
      }
    };
    
    obj.foo() // obj
    (obj.foo = obj.foo)() // window
    (false || obj.foo)() // window
    (1, obj.foo)() // window
    

    后三种调用的运行环境都是全局环境,因此this指向了window
    可以这样理解,JavaScript 引擎内部,obj和obj.foo储存在两个内存地址,称为地址一和地址二。obj.foo()这样调用时,是从地址一调用地址二,因此地址二的运行环境是地址一,this指向obj。但是,上面后三种情况,都是直接取出地址二进行调用,这样的话,运行环境就是全局环境,因此this指向全局环境。后三种情况等同于下面的代码。

    // 情况一
    (obj.foo = function () {
      console.log(this);
    })()
    // 等同于
    (function () {
      console.log(this);
    })()
    
    // 情况二
    (false || function () {
      console.log(this);
    })()
    
    // 情况三
    (1, function () {
      console.log(this);
    })()
    

    如果this所在的方法不在对象的第一层,这时this只是指向当前一层的对象,而不会继承更上面的层。

    var a = {
      p: 'Hello',
      b: {
        m: function() {
          console.log(this.p);
        }
      }
    };
    
    a.b.m() // undefined
    

    因为a.b.m方法在a对象的第二层,这时方法中的this指向了a.b。所以它找不到a中的p属性。也就是说,上面的a.b.m() == (a.b).m()

    使用this时的其它注意事项

    1. 避免多层this
      在函数中多层使用this会导致深层this指向不明。
    var o = {
      f1: function () {
        console.log(this);
        var f2 = function () {
          console.log(this);
        }();
      }
    }
    
    o.f1()
    // Object
    // Window
    

    上面的代码实际上可以视为这样

    var temp = function () {
      console.log(this);
    };
    
    var o = {
      f1: function () {
        console.log(this);
        var f2 = temp();
      }
    }
    

    解决方法有二。一是用一个临时变量来记住this,二是使用箭头函数。

    var o = {
      f1: function() {
        console.log(this);
        var that = this;
        var f2 = function() {
          console.log(that);
        }();
      }
    }
    
    o.f1()
    // Object
    // Object
    

    箭头函数的this指向自己的上一层的this。下例中f2的this就指向了f1的this。

    var o = {
      f1: function() {
        console.log(this);
        var f2 = ( () => console.log(this) )();
      }
    }
    
    o.f1()
    // Object
    // Object
    

    顺便一提,如果使用了JS的严格模式。若函数内部的this指向了顶层对象,就会直接报错。

    1. 在处理数组时使用this。
      数组的mapforeach方法,允许提供一个函数作为参数。这个函数内部不应该使用this。
    var o = {
      v: 'hello',
      p: [ 'a1', 'a2' ],
      f: function f() {
        this.p.forEach(function (item) {
          console.log(this.v + ' ' + item);
        });
      }
    }
    
    o.f()
    // undefined a1
    // undefined a2
    

    同样的,里面的this指向了window对象。
    解决方法之一同上,用一个中间变量记住this。还有一个方法是把this作为foreach的第二个参数,固定它的运行环境。

    var o = {
      v: 'hello',
      p: [ 'a1', 'a2' ],
      f: function f() {
        this.p.forEach(function (item) {
          console.log(this.v + ' ' + item);
        }, this);
      }
    }
    
    //也可以用箭头函数改写:
    var o = {
      v: 'hello',
      p: [ 'a1', 'a2' ],
      f: function f() {
        this.p.forEach((item) => {
          console.log(this.v + ' ' + item);
        });
      }
    }
    
    
    o.f()
    // hello a1
    // hello a2
    

    3.不在回调函数里用this
    回调函数中的this往往会改变指向,最好避免使用。

    var o = new Object();
    o.f = function () {
      console.log(this === o);
    }
    // jQuery 的写法
    $('#button').on('click', o.f);
    

    上面代码中,点击按钮以后,控制台会显示false。原因是此时this不再指向o对象,而是指向按钮的 DOM 对象,因为f方法是在按钮对象的环境中被调用的。这种细微的差别,很容易在编程中忽视,导致难以察觉的错误。

    为了解决这个问题,可以采用一些方法对this进行绑定,也就是使得this固定指向某个对象,减少不确定性。`

  • 相关阅读:
    Document
    Document
    Document
    Document
    Document
    Document
    Document
    Document
    export和import 输出/接收模块变量的接口
    webpack:(模块打包机)
  • 原文地址:https://www.cnblogs.com/Nullc/p/12876422.html
Copyright © 2020-2023  润新知