• this指向问题


    1、全局环境下

    在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;

    1 this.a = 37;
    2 window.a // 37

    2. 函数上下文调用

    1) 、函数直接调用

    普通函数内部的this分两种情况,严格模式和非严格模式

    非严格模式下,this指向全局对象window

    1 function fn(){
    2    return this;  
    3 }
    4 
    5 fn === window;  // true

     严格模式下,this为undefined

    function foo(){
      "use strict";
      return this;    
    }
    
    foo === undefined; // true

    2)、对象中的this

    对象内部方法的this指向调用这些方法的对象

      1. 函数的定义位置不影其this的指向,this指向只和调用函数的对象有关。

      2. 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象,而非window)。

    // 第一种
    var o = {
      prop: 37,
      f: function() {
      console.log(this);
        return this.prop;
      }
    };
    console.log(o.f());  //37
    var a = o.f;         // this 指向window
    console.log(a());  //undefined
    
    var o = {prop: 37};
    
    function independent() {
      return this.prop;
    }
    
    o.f = independent;
    
    console.log(o.f()); // logs 37
    
    // 第二种
    o.b = {
      g: independent,
      prop: 42
    };
    console.log(o.b.g()); // logs 42

    3)、原型链中this

    原型链中的方法的this任然指向调用它的对象

    可以看出, 在p中没有属性f,当执行p.f()时,会查找p的原型链,找到 f 函数并执行,但这与函数内部this指向对象 p 没有任何关系,只需记住谁调用指向谁。

    以上对于函数作为getter & setter 调用时同样适用。

    4)、构造函数中this

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

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

    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)、call & apply 

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

    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"}

    6)、bind方法

    bind方法在ES5引入, 在Function的原型链上,Function.prototype.bind。通过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

    3、DOM事件处理函数中的this& 内联事件中的this

    DOM 事件处理函数

    1. 当函数被当作间挺事件处理函数时,其this,指向处罚该事件的元素(针对addEventListener事件)

      // 被调用时,将关联的元素变成蓝色
        function bluify(e){
          //在控制台打印出所点击元素
          console.log(this);
          //阻止时间冒泡
          e.stopPropagation();
          //阻止元素的默认事件
          e.preventDefault();      
          this.style.backgroundColor = '#A5D9F3';
        }
    
        // 获取文档中的所有元素的列表
        var elements = document.getElementsByTagName('*');
    
        // 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
        for(var i=0 ; i<elements.length ; i++){
          elements[i].addEventListener('click', bluify, false);
        }

    2.内联事件

    内联事件中的this指向分两种情况

      * 当代码被内联处理函数调用时,它的this指向监听所在的DOM元素

      * 当代码被包括在函数内部执行时,其this指向等同于*****函数直接调用情况*****,即在非严格模式指向全局对象window,严格模式指向undefined

    3、setTimeout & setInterval

    对于延时函数内部的回调函数的this指向全局对象window(当然我们可以通过bind方法改变其内部函数的this指向)

    //默认情况下代码
    function Person() {  
        this.age = 0;  
        setTimeout(function() {
            console.log(this); // window
        }, 3000);
    }
    
    var p = new Person();//3秒后返回 window 对象
    ==============================================
    //通过bind绑定
    function Person() {  
        this.age = 0;  
        setTimeout((function() {
            console.log(this); // p 对象
        }).bind(this), 3000);
    }
    
    var p = new Person();//3秒后返回构造函数新生成的对象 Person{...}

    4、箭头函数中的this

    由于箭头函数不绑定this,它会捕获其所在(即定义的位置)上下文的this的值,作为自己的this值

     1)、所以call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的this毫无影响。

     2)、考虑到this时词法层面上的,严格模式中与this相关的规则都将被忽略。(可以忽略是否在严格模式下的影响)

    var adder = {
      base : 1,
        
      add : function(a) {
        var f = v => v + this.base;
        return f(a);
      },
    
      addThruCall: function inFun(a) {
        var f = v => v + this.base;
        var b = {
          base : 2
        };
                
        return f.call(b, a);
      }
    };
    
    console.log(adder.add(1));         // 输出 2
    console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3,其内部的this并没有因为call() 而改变,其this值仍然为函数inFun的this值,指向对象adder

    箭头函数this指向全局window对象,而普通函数则指向调用它的对象

    转载来源 http://www.cnblogs.com/dongcanliang/p/7054176.html

  • 相关阅读:
    Python max() 函数
    Python log10() 函数
    Python log() 函数
    Python fabs() 函数
    Java开源-astar:A 星算法
    9款超绚丽的HTML5/CSS3应用和动画特效
    Java中处理异常的9个最佳实践
    Java泛型
    Android界面性能调优手册
    正确使用Android性能分析工具——TraceView
  • 原文地址:https://www.cnblogs.com/fan-jing/p/10558499.html
Copyright © 2020-2023  润新知