this是javascript的众多关键字之一,它自动定义于作用域内,很多初学者可能对this指向问题感到摸不着头脑。首先看下面的示例
var hero ={};
hero.name = "CJF";
//此处使用具体对象
hero.getName = function(){
console.log(hero.name);//这个确定了我们访问的是hero这个对象的name属性
}
hero.getName();//输出 "CJF"
//在此处我们使用this
hero.getNameNew = function(){
console.log(this.name);//这个则要根据具体的运行环境来判定this指向
}
hero.getNameNew()//也输出 "CJF" 此时的this对象指向的hero这个对象
当然我们也可以在浏览器控制台直接输入this看具体的结果
从上图看一看出,此时this指向的window对象。
this的指向大概可以分为四种
1、普通函数调用
2、作为对象的方法调用
3、作为构造函数使用
4、call和apply调用
第一种 作为普通函数调用
//函数声明
function fn(){
console.log(this);//windwo对象
}
//函数表达式
var f = function(){
console.log(this);//windwo对象
};
fn();
f();
//不管此时是调用fn或者f函数,它们中的this指向的都是window对象
也就是当一个函数作为普通函数调用时,内部的this对象指向的全局对象,即浏览器的window对象。
当然在ECMAScript5的严格模式下,this已经被规定不在指向全局对象了,而是undefined
function fun(){
"use strict"
console.log(this);//输出undefined
}
fun();
第二种 作为对象的方法调用
就如前面的hero示例所示的
var hero = {
name:"CJF",
getName:function(){
console.log(this.name);
}
}
hero.getName();//输出 "CJF"
也就是说当函数作为对象的方法调用时,this指向的就是该对象。
不过大家要注意一点儿,如果像下面这样调用,this就不再指向该对象了
var hero = {
name:"CJF",
getName:function(){
console.log(this.name);
}
}
window.name = "123";
var getName = hero.getName; //将hero.getName方法的引用赋值给另一个变量,再通过这个变量调用该方法,此时this是window对象,不再是hero对象
getName();//输出 "123" 相当于普通函数调用
第三种 作为构造函数使用
当我们是使用new关键字调用函数时,总是返回一个对象,构造器中的this就指向该对象
function FClass(name){
this.name = name;
}
var obj = new FClass("CJF");
console.log(obj.name);//输出 "CJF"
如果构造函数显式的返回一个Object类型的对象,那么我们期待的this就不会被返回。
如果构造函数不显式的返回任何数据或者显式返回的不是对象类型数据,使用new调用函数,返回的还是我们期待的this。
//构造函数显式返回对象类型数据
function FClass(name){
this.name = name;
return {
name:"CJF1",
age:20
};
}
var obj = new FClass("CJF");
console.log(obj.name);//输出 "CJF1"
console.log(obj.age);//输出 20
//构造函数显式返回非对象类型数据
function FClass(name){
this.name = name;
return "CJF1";
}
var obj = new FClass("CJF");
console.log(obj.name);//输出 "CJF"
console.log(obj.age);//输出 undefined
第四种 call和apply调用
call和apply调用跟普通函数调用相比,call和apply可以动态的改变传入函数的this对象指向。
var obj = {
name:"CJF",
getName:function(){
console.log(this.name);
}
}
var obj1 = {
name:"CJF1"
}
console.log(obj.getName());//输出 "CJF"
console.log(obj.getName.call(obj1));//输出 "CJF1"
//或者
console.log(obj.getName.apply(obj1));//输出 "CJF1"
//如果call和apply不传任何参数或者传入null 则this指向window对象
window.name == "123";
console.log(obj.getName.call());//输出 "123"
console.log(obj.getName.apply());//输出 "123"
console.log(obj.getName.call(null));//输出 "123"
console.log(obj.getName.apply(null));//输出 "123"
call和apply具体使用请参考我的另一篇博客 apply、call的区别和使用
this总是指向一个对象,this对象具体指向的是哪个对象是在运行时基于函数的执行环境动态绑定的,不是函数声明时的环境。
在js中this的使用是非常普遍的,上面介绍的四种关于this指向的四种情况和规则,在实际写代码的过程中肯定比这要复杂的多(各种框架和js库),但是无论它们的代码多么复杂,它们的this运用基本都是混合应用上面的几个情况和规则而已。