1、this

JavaScript中的this,总是指向一个对象 ,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境
this的指向大致可以分以下4种:

  • 作为对象的方法调用
  • 作为普通函数调用
  • 构造器调用
  • Function.prototype.call或Function.prototype.apply调用

1、作为对象的方法调用

var obj =  {
name:"Tome",
getName:function(){
alert(this == obj); // true
alert(this.name); // Tome
}
};
obj.getName();

因为obj字面量对象调用了getiName()方法,所以this就代表了obj字面量对象。字面量对象一创建就在内存中有自己的空间。
2、作为普通函数调用
当函数不作为对象的属性被调用时,此时this总是指向全局对象。在浏览器的JavaScript中,这个全局对象就是window对象。

var name = "globalName";
var getName = function(){
return this.name;
};
alert(getName());

window.name = "globalNameA";
var getName = function(){
return this.name;
};
alert(getName());

window.name = "globalNameB";
var myObject = {
name:"Jhony",
getName:function(){
return this.name;
}
}
var getName = myObject.getName;
alert(getName()); // globalNameB
alert(myObject.getName()); // Jhony

var getName = myObject.getName这一句只是把myObject字面的对象方法借来用。而里面用到的this是根据具体的运行环境来绑定的,所以当在myObject字面量对象外且不作为myObject的属性来调用getName方法时,this指向全局对象。当作为myObject对象的属性来调用时,即myObject.getName()调用时,this又指向字面量对象myObject。
注意:有个很趣的现象

window.id = "window";
document.getElementById("root").onclick = function(){
alert(this.id); // root
var callback = function(){
alert(this.id);
};
callback(); // window
}

此时callback里的this是指向了全局对象window而不是id为root的元素对象,为什么会这样呢,因为callback方法前面没有指明调用对象,callback方法不是作为id为root元素对象的属性来调用的,所以this默认指向全局对象。如果你要callback方法里的this指向id为root元素,怎么办?可以通过call或apply方法,重新指定this的指向,如:

.id = "window";
document.getElementById("root").onclick = function(){
alert(this.id); // root
var callback = function(){
alert(this.id);
};
callback.call(document.getElementById("root")); // root
callback.apply(document.getElementById("root")); // root
}

3、构造器调用
JavaScript中没有类,但是可以从构造器中创建对象,同时也提供了new运算符,但他们只是用来申请一个内存空间,然后通过这个构造器方法来对这个空间进行赋值。

var MyClass = function(name){
this.name = name;
}

function MyClass1(name){
this.name = name;
}

var myClass = new MyClass("Tome");
alert(myClass.name)
var myClass1 = new MyClass1("Haha");
alert(myClass1.name)

构造器会帮我们申请内存空间后,然后把这个对象隐式地返回来,再用构造器方法对其进行赋值。不要在构造器中显示return返回其他东西,否则将会取代之前申请好的对象。前面的功夫就白做了,如:

var MyClass = function(name){
this.name = name;
return {
name:"Jeety"
}
}
var myClass = new MyClass("Tome");
alert(myClass.name) // Jeety

上面这个反例里做事就是一开始去申请了内存空间,然后用构造器函数对内存空间进行了赋值,让内存有了一个name值为Tome,结果在最后又去创建了一个字面量对象,在内存另开一个空间,把name赋值了Jeety,最后把前面那个抛弃了,返回这个字面量对象。不要这样做, 我真想说,这是吃饱了撑的吗?

4、Function.prototype.call或Function.prototype.apply调用

.id = "window";
document.getElementById("root").onclick = function(){
alert(this.id); // root
var callback = function(){
alert(this.id);
};
callback();
callback.call(document.getElementById("root")); // root
callback.apply(document.getElementById("root")); // root
}

上面的callback函数里的this是指向了全局对象window而不是id为root的元素对象,为什么会这样呢,因为当函数不作为对象的属性被调用时,此时this总是指向全局对象。而callback方法前面没有指明调用对象,即没有作为id为root的元素对象的属性来调用,所以this指向全局对象。如果你要callback方法里的this指向id为root元素,怎么办?可以通过call或apply方法,重新指定this的指向,如上所示。

谢谢阅读!