美文网首页
无标题文章this的用法

无标题文章this的用法

作者: divine_zhouo | 来源:发表于2017-09-12 14:39 被阅读0次

    原文链接:https://segmentfault.com/a/1190000008590012

    一、全局上下文

    在全局运行上下文中(在任何函数体外部),this指代全局对象,无论是否在严格模式下。在浏览器中,全局对象为window对象。

    console.log(this.document === document); // true
    console.log(this === window); // true
    this.a = 37;
    console.log(window.a); // 37
    

    二、函数上下文

    在函数内部,this的值取决于函数是如何调用的。

    1、直接调用
    在非严格模式下,this的值不会在函数执行时被设置,此时的this的值会默认设置为全局对象。
    function foo(){
     return this;
    }
    
    foo() === window; // true
    
    在严格模式下,this将保持他进入执行环境时的值,所以下面的this将会默认为undefined
    function foo(){
      "use strict"; // 严格模式
      return this;
    }
    
    foo() === undefined; // true
    
    在严格模式下,如果this未被执行的上下文环境定义,那么它将会默认为undefined。
    2、对象方法中的this

    当以对象里的方法的方式调用函数时,它们的this是调用该函数的对象。

    下面的例子中,当obj.f()被调用时,函数内的this将绑定到obj对象。
    var obj = {
        prop: 37,
        foo: function() {
           return this.prop;
        }
    };
    
    console.log(obj.foo()); // 37
    

    注意,在何处或者如何定义调用函数完全不会影响到this的行为。

    在上一个例子中,我们在定义obj的时候为其成员foo定义了一个匿名函数。但是,我们也可以首先定义函数然后再将其附属到obj.foo。这样做this的取值也和上面一致:

     var obj = { prop: 37 };
    
    function independent() {
       return this.prop;
    }
    
    obj.foo = independent;
    
    console.log(obj.foo()); // 37
    
    这说明this的值只与函数foo作为obj的成员被调用有关系。

    类似的,this的绑定只受最靠近的成员引用的影响。

    在下面的这个例子中,我们把一个方法g当作对象obj.b的函数调用。

    在这次执行期间,函数中的this将指向obj.b。事实上,这与对象本身的成员没有多大关系,最靠近的引用才是最重要的。
    var obj = { prop: 37 };
    
    function independent() {
      return this.prop;
    }
    
    obj.b = {
      g: independent,
      prop: 42
    };
    
    console.log(obj.b.g()); // 42
    
    3、原型链中的this

    相同的概念在定义在原型链中的方法也是一致的。

    如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,表现得好像是这个方法就存在于这个对象上一样。
    var obj = {
       f : function(){ 
        return this.a + this.b; 
      }
    };
    var p = Object.create(obj);
    p.a = 1;
    p.b = 4;
    
    console.log(p.f()); // 5
    

    在这个例子中,对象p没有属于它自己的f属性,它的f属性继承自它的原型。但是这对于最终在obj中找到f属性的查找过程来说没有关系;查找过程首先从p.f的引用开始,所以函数中的this指向p。也就是说,因为f是作为p的方法调用的,

    所以它的this指向了p。这是JavaScript的原型继承中的一个有趣的特性。
    4、getter与setter中的this

    相同的概念也适用时的函数作为一个getter或者setter调用。作为getter或setter函数都会绑定this到从设置属性或得到属性的那个对象。

    function modulus(){
       return Math.sqrt(this.re * this.re + this.im * this.im);
    }
    
    var obj = {
      re: 1,
      im: -1,
      get phase(){
        return Math.atan2(this.im, this.re);
      }
    };
    
    Object.defineProperty(obj, 'modulus', {
      get: modulus,
      enumerable: true,
      configurable: true
    });
    
    console.log(obj.phase, obj.modulus); // -0.785 1.414
    
    5、构造函数中的this
    当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。

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

    function Fn(){
       this.a = 37;
    }
    
    var obj = new Fn();
    console.log(obj.a); // 37
    
    function Foo(){
      this.a = 37;
      return { a: 38 };
    }
    
    obj = new Foo();
    console.log(obj.a); // 38
    
    6、call和apply

    当一个函数的函数体中使用了this关键字时,通过所有函数都从Function对象的原型中继承的call()方法和apply()方法调用时,

    它的值可以绑定到一个指定的对象上。
     function add(c, d){
       return console.log(this.a + this.b + c + d);
     }
    
     var obj = {
        a: 1,
        b: 3
     };
    
     add.call(obj, 5, 7); // 1 + 3 + 5 + 7 = 16
     add.apply(obj, [10, 20]); // 1 + 3 + 10 + 20 = 34
    

    使用call和apply函数的时候要注意,如果传递的this值不是一个对象,JavaScript将会尝试使用内部 ToObject操作将其转换为对象。因此,如果传递的值是一个原始值比如7或foo,那么就会使用相关构造函数将它转换为对象,所以原始值7通过new Number(7)被转换为对象,而字符串foo使用new String('foo')转化为对象,例如:

    function bar() {
      console.log(Object.prototype.toString.call(this));
    }
    
    bar.call(7); // [object Number]
    
    7、bind()方法

    ECMAScript 5引入了Function.prototype.bind。调用fn.bind(someObject)会创建一个与fn具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

    function fn(){
      return this.a;
    }
    
    var g = fn.bind({ a: "azerty" });
    console.log(g()); // "azerty"
    
    var obj = {
      a: 37,
      foo: fn,
      go: g
    };
    console.log(obj.foo(), obj.go()); // 37, "azerty"
    
    8、DOM事件处理函数中的this

    当函数被用作事件处理函数时,它的this指向触发事件的元素(一些浏览器在动态添加监听器时不遵守这个约定,除非使用addEventListener)。

    // 获取文档中的所有元素的列表
    var elements = document.getElementsByTagName('*');
    
    for(var i = 0; i < elements.length; i++){
      // 当元素被点击时,就会变成蓝色
      elements[i].addEventListener('click', function (e) {
        e.stopPropagation();
        console.log(this);
        console.log(e.currentTarget);
        console.log(e.target);
     // 上面3个值是一样的
        this.style.backgroundColor = '#A5D9F3';
      });
    }
    
    9、内联事件处理函数中的this
    当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素:
    <button onclick="alert(this.tagName.toLowerCase());">
      Show this
    </button>
    

    上面的alert会显示button。注意只有外层代码中的this是这样设置的:

    <button onclick="alert((function(){return this})());">
      Show inner this
    </button>
    

    在这种情况下,没有设置内部函数的this,所以它指向global/window对象(即非严格模式下调用的函数未设置this时指向的默认对象)。

    相关文章

      网友评论

          本文标题:无标题文章this的用法

          本文链接:https://www.haomeiwen.com/subject/bfdcsxtx.html