js当中的this指向在创建时并不能确定,而是要看它所在的环境,也就是说不是由定义是决定的,而是由调用时决定的。通常会指向调用它的对象,深入一点的说,它的值取决于调用的模式。而在JavaScript中,一共有4中调用模式:方法调用模式、函数调用模式、构造函数调用模式、apply调用模式。
1. 方法调用模式
当一个函数是作为一个对象的属性时,我们通常称这个函数是这个对象的一个方法。当这个方法被调用时,this就会指向该方法所属对象。
var people = {
name : "Yika",
sayName : function(){
console.log(this.name); //"Yika"
//this已经绑定在了people对象上了 }
}
people.sayName();
2. 函数调用模式
当一个函数被调用时并非某个对象上的方法,那么它就是作为一个函数被调用的。
这种模式调用,this会指向window对象,即使这个函数或许是在外部函数里调用的,
var name = "window-Yika";
var people = {
name: "people-Yika",
student: function() {
console.log(this); //这里的this绑定的是对象people
function sayName() {
var name = "sayName-Yika";
console.log(this.name); //window-Yika
}
sayName();
}
};
people.student();
即使sayName函数本身和它所在的 people对象都有name值,但是this是指向window的。
如果想让函数里的this指向people这个对象,只要在student函数里将this缓存起来。然后再将this通过变量转移到sayName函数里就可以解决啦!
var people = {
name : "people-Yika",
student : function(){
var self = this; //将this缓存起来
function sayName(){
var name = "sayName-Yika";
console.log(self.name); //"people-Yika",此时self指向的是people对象 };
sayName();
}
}
people.student();
3. 构造函数调用模式
同时this也绑定在新对象上
function People(name){
this.name = name; //这里的this,用new调用后便指向了新对象Yika
this.sayName = function(){
console.log(this.name); //输出
}
}
var Yika = new People("Yika");
Yika.sayName(); //输出“Yika" ,因为Yika是通过new调用得来的,this都绑定在了Yika对象上。
4. Apply调用模式
apply方法让我们构建一个参数数组传递给调用函数,也允许我们改变this值。通过apply轻易的修改函数的this绑定对象,和apply相似的方法call也有一样的效果
function People(name){
this.name = name;
this.sayName = function(){
console.log(this.name); //sayName这个方法是属于People构造函数的
}
}
function Student(name){
People.apply(this, arguments);
//借用构造函数的集成方式,就是在Student构造函数里,通过apply调用People构造函数,并改变People的this值
//这样每次创建Student实例时,都会调用People构造函数
}
var student = new Student("Yika");
student.sayName(); //输出“Yika”