美文网首页
Javascript中的this关键字、call和apply

Javascript中的this关键字、call和apply

作者: 初夏_summer | 来源:发表于2016-02-20 23:27 被阅读112次

    this关键字的指向

    this关键字的理解是在很多前端面试题中出现的题目,实际开发中用到的地方也非常多,这里写一下自己的理解~

    在一个方法内部,this是一个特殊变量,它始终指向当前对象。this是动态的,可以改变的。
    eg:

    var n = { 
      name: 'abc', 
      getName: function () { 
                return this.name;
             }
    };
    n.getName; // function n.getName()
    n.getName(); // abc
    

    在上面这段代码中,age function中的this指向的就是n
    换种方法写:

    function getName() { 
      return this.name;
    }
    var n= { 
      name: 'abc', 
      gName: getName
    };
    n.gName(); // abc, 正常结果
    getName(); // NaN
    

    在这段代码中,n.gName()执行时,getName()中的this是指向n的,但是直接调用getName()时,this是指向全局变量window的。
    如果把n.gName()赋给一个变量,像这样:

    var name = n.gName;
    name();
    

    这个时候,function getName中的this却是指向window的,这是因为,在JS中,要保证this指向正确,必须用obj.xxx()的形式调用
    有的时候,在函数内部又写了一个函数,像这样:

    var n= { 
      name: 'abc', 
      getName: function () { 
          function getNewname() {
             return this.name; 
          } 
          return getNewname(); 
      }
    };
    n.getName();
    

    这个时候,在getNewname()中的this,指向的就不是n了,而是window。原因是this指针只在getName方法的函数内指向n,在函数内部定义的函数getNewname()this又指向window了!
    怎么解决这个问题呢?
    getName函数中,用that变量获取到this,然后getNewname函数就可以使用这个that了,就像这样:

    var n= { 
      name: 'abc', 
      getName: function () { 
        var that = this; // 在方法内部一开始就捕获this 
        function getNewname() { 
            return that.name; // 用that而不是this 
        } 
      return getNewname(); 
      }
    };
    n.getName();
    

    这样,就可以放心地在函数内部使用this了。
    另外JS中还有几种调用函数的方式:

    • 在标签内用onclick="show()"的方式调用show函数,这时由于是直接调用了show函数,因此show函数内部的this是指向window的,而如果是onclick="show(this);"这样写,就可以改变this的指向了。
    • addEventListener注册的函数,像这样:
    name = 'window';
    var a = document.getElementsByTagName('body');
    a.addEventListener('click',show());
    function show(){
       alert(this.name);
    }
    

    这时在屏幕上点击一下,alert出来的结果是'window',说明this指的是window

    • 作为构造方法调用,像这样:
    function test(){     
       this.x = 1;   
    }   
    var o = new test();   
    alert(o.x); // 1 
    

    这里this指对象o,所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。
    如果再通过test函数构造出一个对象p,像这样:

    var p = new test();
    alert(p.x);
    

    这个时候,this指的p

    call、apply的理解

    附参考链接:https://www.zhihu.com/question/20289071
    call和apply的存在,就是为了改变函数的调用对象,改变某个函数运行时的 context 即上下文,也就是改变this的指向。
    二者的作用是一样的,只是传递参数的方式不一样。
    call----把参数顺序传递进去,用,隔开
    apply----把参数作为一个数组传递进去
    eg:

    func.call(this, arg1, arg2,arg3);
    func.apply(this, [arg1, arg2,arg3]);
    

    call和apply的应用场景:
    在javascript OOP中,我们经常会这样定义:

    function cat(){}
    cat.prototype={     
       food:"fish",    
       say: function(){           
          alert("I love "+this.food);     
       }
    }
    var blackCat = new cat;
    blackCat.say(); 
    

    但是如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过callapplyblackCatsay方法:blackCat.say.call(whiteDog);
    当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。
    另外,当你的参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments这个数组来便利所有的参数。
    注:
    另外,当apply的参数为空时,this是指向window的。

    相关文章

      网友评论

          本文标题:Javascript中的this关键字、call和apply

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