• javacript中的this指向问题


    this提供了一种更优雅的方式来“传递一个对象的引用
     
    1 浏览器全局环境和node全局环境中的this
    浏览器中的this指向windows,window为浏览器的全局对象。
    console.log(this===window);//true
    node环境中this指向为一个空对象。而global为node的全局对象。
    console.log(this);//{},
    console.log(this===global)://false
     
    2 箭头函数和function关键字函数的this指向总结。
    2.1 function关键字函数
    (1)一般情况this 指向它的调用对象,如果没有调用者则指向全局对象。
    (2)在构造函数下(也就是new function()),this指向被创建的新对象。
    (3)在使用js监听dom事件情况下,this指向触发事件的元素。
    (4)apply,call和bind可以强制改变this的指向,使this的指向为三个处理方法中上送的一个参数对象。
     (5) 在html元素上使用内联事件时,如果调用js中方法或书写代码的情况下this指向当前元素。如果在事件直接使用()()立即执行,则非严格模式下this指向window,严格模式下指向undefined。
    2.2 非箭头函数
      指向箭头函数定义时所处的对象,而不是箭头函数使用(调用)时所在的对象,默认使用父级的this。
      this等同于上一层非箭头函数的this值或全局对象(window或undefined)(严格模式this是undefined)
     
    3 各种情况下的示例分析。
    3.1 在全居环境下定义和调用。
    function 关键字定义函数 
    function fun(){
        // "use strict"; // 这里是严格模式
        return this;
    }
    //true  浏览器环境  这里是非严格模式  在严格模式下指向undefined
    console.log(fun()===window); 
     //treu  node环境  这里是非严格模式  在严格模式下指向undefined
    console.log(fun()===global);
    箭头函数  
    let foo=()=>{
      //  "use strict"; // 这里是严格模式
      return this;  
    }
    this.a="5";
    //true 浏览器环境。严格模式与非严格模式一致
    console.log(foo()===window); 
    //true node环境下 全局的this为一个空对象{},所以这里this指向的是空对象。严格模式与非严格模式一致
    console.log(foo()===this);
    //很显然这里定义的箭头函数指向的是,定义位置所处环境的this。严格模式与非严格模式一致
    console.log(foo());//{a:'5'},
    3.2 对象中this的调用
    function 关键字定义函数 
    let obj={
        a:"aa",
        foo:function(){
            return this;
        }
    }
    //true  浏览器环境与node环境一致。
    console.log(obj.foo()===obj);
    //obj中没有this这个属性,这里等于undefined。 
    //console.log(obj.this); 
    let a=obj.foo;
    console.log(a())   //node 为global  浏览器为window
    注:对于多层嵌套对象的调用,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。
    箭头函数 
    let obj={
        a:"aa",
        foo:()=>{
            return this;
        }
    }
    //true  浏览器环境与node环境一致。
    console.log(obj.foo()===window); 
    //在node中,指向全局this中指向的空对象。
    this.a="aa";
    //{a:'aa'} node环境
    console.log(obj.foo());
    注:对于嵌套的多层对象来说,都是指向window。
     
    3.3 构造函数中的this
    function 关键字定义函数 
    当构造函数没有返回时 this指向new 所以创建的新对象。 浏览器环境与node环境是一致的。
    function C(){
        console.log(this); //{}
        this.a='a'; 
    }
    let d=new C();
    console.log(d);//{a:'a'}
    注:由于箭头函数的this更像是进行了某种操作透传(继承)作用域的this,因此箭头函数我的理解是没有this的, 所以箭头函数不能作为构造函数。会抛出一个VM1565:5 Uncaught TypeError: C is not a constructor
    3.4 call,apply和bind强制改变this的指向
    function 关键字定义函数
    function foo(){
        console.log(this);
        console.log(...arguments);
    }
    let a={b:'b',foo:foo};
    foo();  //浏览器环境输出 window ;node环境输出 global
    a.foo(); //输出a对象。
    let c={c1:'c1'}; 
    let d=[1,2,3,4];
    foo.call(c,...d);//{ c1: 'c1' },1 2 3 4
    foo.apply(c,d);//{ c1: 'c1' },1 2 3 4
    let foo2 = foo.bind(c,...d);
    foo2(88,99); //{ c1: 'c1' } ,1 2 3 4 88 99
    注;由于箭头函数没有自身的this,它的this是继承的,所以无法强制改变this的指向。箭头函数也没有arguments。
    但如果强制使用不能改变其this指向。可以传入函数定义时的指定参数个数。
    let foo=(a,b,c)=>{
        console.log(this); //浏览器环境 this都输出为window。node环境 this都输出为{}
        console.log(a,b,c);//都输出为1,2,3
    }
    let c={c1:'c1'}; 
    let d=[1,2,3,4];
    foo.call(c,...d);
    foo.apply(c,d);
    let foo2 = foo.bind(c,...d);
    foo2(88,99); 
     
    3.5 dom事件和内联事件
    dom绑定事件
      <div>我是dom绑定事件</div>
       <span>我是span</span>
       <button >哈哈哈</button>
       <script>
          // 被调用时,将关联的元素变成蓝色
          function doClick(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', doClick, false);
        }
        </script>

    内联事件:

     <button onclick="console.log(this)" >click me </span>
     <button onclick="(function(){console.log(this)})()" >Non strict mode</span>
     <button onclick="(()=>{console.log(this)})()" >Non strict mode Arrow function </span>
     <button onclick="(function(){'use strict'; console.log(this)})()" >use strict</button>

     

    3.6 setTimeout & setInterval
    function 关键字定义函数 
    let a={a:'aa'};
    setTimeout(function(){console.log(this)},2000);  //浏览器环境过两秒输出 window ;node环境输出 一个Timeout对象。
    setTimeout((function(){console.log(this)}).bind(a),3000); //可通过bind改变this指向
    箭头函数 
    setTimeout(()=>{console.log(this)},2000); //浏览器环境,输出window,node环境输出{}
    最后个人总结:箭头函数本身是没有this的,其this是继承函数定义(如果定义的作用域也是箭头函数,则往上继续继承,知道作用域有this为止)时所处作用域链中离它最近的this。
    非常感谢很多前辈的优秀博客为我提供了巨大的帮助,感谢名单在此不一一列举。本博客仅供参考学习,不做盈利目的。如果错误,欢迎指正。
     
  • 相关阅读:
    Java8 新特性 (七)
    Java8 新特性 (六)Optional 类
    Java8 新特性 (四)方法引用与构造器引用
    使用Postman做接口测试(一)
    使用unittest方法写登录接口,调用cookie
    python的简单实用二(封装/继承/多态)
    学习进度条46
    学习进度条104
    学习进度条103
    学习进度条102
  • 原文地址:https://www.cnblogs.com/bojunyixiao/p/15232076.html
Copyright © 2020-2023  润新知