Javascript中的this关键字、call和apply

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)