• javascript中让你捉摸不定的this


    this到底指向谁,估计很多人在使用javascript的过程中都遇到过,这个关键字如果没搞懂,在一些高级功能中都会困难重重,搜了下相关文章,介绍的都挺多的,也有很深入的,比如汤姆大叔的《深入理解javascript系列》文章。看到很多文章中提到一句话:"this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象"。

    《javascript设计模式与实践》中是这样说的:javascript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境

    除去不常用的with和eval,实际应用中,this的指向大致分为下面4种情况:

    1、作为对象的方法调用。

    2、作为普通函数调用。

    3、构造器函数调用。

    4、call和apply调用。

    情况1:作为对象的方法调用

    当函数作为对象的方法调用时,this指向该对象。这是最常见的,比如:

    var obj={
      a:1,
      fun:function(){
        console.log(this.a);//输出:1
      }
    };
    obj.fun();
    

    情况2:作为普通函数调用

    当函数不作为对象的属性调用时,即作为普通函数调用,this总是指向全局对象。

    var a=1;
    function fun(){
      var a=2;
      console.log(this.a);//输出:1
     console.log(a);//输出:2 } fun();

    再看一种情况:

    var name="张三";
    var obj={
      name:"李四",
      getName:function(){
        console.log(this.name);
      }
    }
    obj.getName();//输出:李四
    var getName=obj.getName;
    getName();//输出:张三
    

     直接调用obj.getName(),这里的this是作为对象的方法调用,所以它指向obj,this.name就是李四;

    obj.getName赋值给getName后,getName就变成了普通函数,所以指向的是全局的window.name,结果是张三;

    举个在实际开发过程中遇到的会让人困惑的例子:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body>
      <button id="btn">点我</button>
      <script type="text/javascript">
        var id="window";
        document.getElementById("btn").onclick=function(){
          alert(this.id);//输出:btn
          var callback=function(){
            alert(this.id);//输出:window
          }
          callback();
        }
      </script>
    </body>
    </html>
    

      点击按钮的时候this指向的是按钮,但是callback是作为普通函数调用的,里面的this指向的是全局对象window,所以结果是window。

    此时我们可以临时用一个变量保存对当前对象的引用:

    var id="window";
        document.getElementById("btn").onclick=function(){
          var self=this;
          var callback=function(){
            alert(self.id);//输出:btn
          }
          callback();
       }
    

    情况3:构造器中调用

    function myClass(){
      this.name="张三";
    }
    var child=new myClass();
    console.log(child.name);//输出:张三
    

    大部分的javascript函数都可以当做构造函数来使用,构造器函数外表跟普通函数一模一样,区别在于调用的方式。当使用new运算符调用函数时,该函数总会返回一个对象,就是我们常说的实例对象。通常情况下,通过new运算符后,构造器函数中的this就指向的实例对象。

    注意:如果构造器函数显式的返回了一个object类型的休息,那么运算结果最终会返回这个对象,而不是上面所期望的。例如:

    function myClass(){
      this.name="张三";
      return {
        name:"李四"
      }
    }
    var child=new myClass();
    console.log(child.name);//输出:"李四"
    console.log(child);//输出:[object Object] {name: "李四"}
    

      

     这个例子与上面的例子差别就在于构造器函数最后返回了一个对象。如果构造器函数不显式的返回任何数据,或者返回一个非对象类型的数据,就不会出现这种情况,例如:

    function myClass(){
      this.name="张三";
      return "李四"
    }
    var child=new myClass();
    console.log(child.name);//输出:张三
    console.log(child);//输出:[object Object] {name: "张三"}

    情况4:call和apply

    call和apply能够动态的修改传入函数的this:

    var obj1={
      name:"张三",
      getName:function(){
        console.log(this.name);
      }
    };
    var obj2={
      name:"李四"
    };
    obj1.getName();//输出:"张三"
    obj1.getName.call(obj2);//输出:"李四"
    obj1.getName.apply(obj2);//输出:"李四"
    

      

    call和apply的作用这里就不详细说了。

  • 相关阅读:
    JDOJ 1090: 矩阵
    JDOJ 2236: Random Num
    浅谈区间DP
    NOIP 2006 能量项链
    小技巧—处理环形区间
    NOI 1995 石子合并
    洛谷 P5640 【CSGRound2】逐梦者的初心
    JDOJ 1101: 邦德I
    JDOJ 1104: 最佳挑水
    JDOJ 1098: 夏娜的菠萝包
  • 原文地址:https://www.cnblogs.com/hutuzhu/p/5341821.html
Copyright © 2020-2023  润新知