JavaScript学习笔记 (3) this详解

概览

this关键字在Javascript中的表现和其他语言略有不同。在严格模式和非严格模式下同样存在区别。在大部分情形下,this的值由函数的调用方式所决定。

全局上下文

全局环境中,this指代全局对象,无论是否在严格模式。

 console.log(this===window);//true
 
 this.a=37;
 console.log(window.a);//37

函数上下文

  • 非严格模式下:
 function f1(){
  return this;
 }
 
 f1()===window; //true
  • 严格模式下:
 function f2(){
  "use strict";
  return this;
 }
 
 f2()===undefined;//true

在普通函数调用中,非严格模式下,并且没有用****call****或者****apply****指定****this****的值,那么****this****默认设置为全局变量;在严格模式下,****this****的值等于它进入执行作用域时被设定的值****.****在上例中****this****没有被赋予任何值,所以它等于默认值****undefined****

对象方法中的this

当以对象里的方法的方式调用函数时,它们的this是调用该函数的对象。

var object={
  value:10,
  getValue:function(){
    return this.value;
  }
};

console.log(object.getValue()); // 输出10

构造函数中的this

当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。

 var Person=function(){
  this.age=20;
 }
 
 var mario=new Person();
 console.log(mario.age); //输出20

call 和 apply

call 和 apply是为了动态改变this而出现的,当一个Object没有某个方法,但是其他的有,则可以借助call或apply用其他对象的方法来操作。

 function printInfo(gender,age){
  alert(this.name+" is a "+gender+" and "+age+" years old ");
 }
 
 var person={
  name:"mario"
 };
 
 printInfo.call(person,"man","20");//mario is a man and 20 years old.
 printInfo.apply(person,["man","20"]);//mario is a man and 20 years old.

call和apply的区别

foo.call(this,arg1,arg2,arg3)==foo.apply(this,[arg1,arg2,arg3])==this.foo(arg1,arg2,arg3)
//this是想指定的上下文

****JS****中,某个函数的参数数量是不固定的。所以当参数明确知道数量时,用****call****,而不确定的时候,用****apply****,然后将参数****push****进数组,当参数数量不确定时,函数内部也可以通过****arguments****这个数组来遍历所有的参数。

bind方法

ES5中引入了Function.prototype.bind. 调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久的被绑定到了bind的第一个参数,无论这个函数时如何被调用的。

 function origin(){
  return this.value;
 }
 
 var bind=origin.bind({value:"abcd"});
 console.log(bind());// "abcd"
 
 var object={value:100, origin:origin,bind: bind}
 console.log(object.origin(),object.bind()); //100,"abcd"

上面这段代码首先声明了一个原有函数origin,然后用origin函数创建了一个与origin具有相同函数体和作用域的函数bind,在bind函数中,this被永久的绑定到了第一个参数也就是"abcd",所以在最后我们创建一个新的同时带有origin和bind函数的实例object后,origin函数中的this指代的是object本身,所以能输出object本身的value值100,但bind中的this已经无法改变,this.value将永远等于"abcd".

DOM中的this

当函数被用作事件处理函数时,它的this指向触发事件的元素。(这一点和前面对象方法中的this相似)

假设我们有一个id为"test"的按钮:

 var button=document.getElementById("test");
 button.setEventListener("click",function(){
  alert(this.id);  //输出了按钮的id:test
 });

由此可见这里this指向的就是触发click事件的元素--id为“test”的按钮。

总结

综上所述,this出现的场景可以被分为四类:

  • 有对象就指向调用对象(无论是对象方法中还是DOM中)
  • 没调用对象就指向全局对象
  • 用new构造的就指向被创建的新对象
  • 通过apply或call或bind可以改变this的指向

参考

  • MDN this
  • 如何理解和熟练运用js中的call和apply
  • alsotang的博客

你可能感兴趣的:(JavaScript学习笔记 (3) this详解)