JavaScript中的this指向问题
注意:函数定义无法确定this指向,函数执行的才可以,因此需要知道函数的调用方式。
1、普通函数调用
var a='hello world';
function f1(){
console.log(this);//window
console.log(this.a);//hello world
}
window.f1();
解析:window是js中的全局对象,我们创建的变量实际上是给window添加属性。一般情况下,普通函数调用前边的window省略不写。这里window调用了f1函数,所以this指向了window,a是全局变量,相当于window的属性,因此当普通函数被调用,this指向window的时候,是可以访问到a这个变量的。当然了,下边的写法是一样的意思。
function f1(){
this.a='hello world';
console.log(this);//window
console.log(this.a);//hello world
}
window.f1();
2、作为方法来调用
var name='张三';
var person={
name:'李四',
f1:function(){
console.log(this);
console.log(this.name);
}
};
person.f1();//this指向person,name是李四
var f2=person.say;
f2();//this指向window,name是张三
解析:这里将person.f1方法赋给f2变量,此时f2变量相当于window对象的一个属性,因此f2执行的时候相当于window.f2(),即window对象调用f2这个方法,所以this关键字指向window,再换一种情况进行说明,即使personB中的方法是将personA中的方法进行赋值给了f2,但是在掉用的时候,因为是person进行了调用,所有this依然指向的是personB
var personA={
name:'张三',
f1:function(){
console.log(this)
console.log(this.name);
}
};
var personB={
name:'李四',
f2:personA.f1
};
personB.f2();//this指向personB,输出名字是李四
3、作为构造函数进行调用
function Person(name){
this.name=name;
}
var personA=Person("xl");
console.log(personA.name); // 输出 undefined
console.log(window.name);//输出 xl
//上面代码没有进行new操作,相当于window对象调用Person("xl")方法,那么this指向window对象,并进行赋值操作window.name="xl".
var personB=new Person("xl");
console.log(personB.name);// 输出 xl
4、call和apply方法的调用
var name='HELLO WORLD';
var animal={
name:'hello world',
run:function(){
console.log(this);
console.log(this.name);
}
};
animal.run();//this指向animal这个对象,this.name输出hello world
animal.run.call();//call参数为空的情况下,this改变之后指向window.this.name输出HELLO WORLD
/*FruitA是一个构造函数,有属性n1和n2以及change方法,change方法可以传递的参数为属性赋值*/
function FruitA(n1,n2){
this.n1=n1;
this.n2=n2;
this.change=function(x,y){
this.n1=x;
this.n2=y;
}
}
/*构造函数实例化对象并传入参数*/
var fruitA=new FruitA("cheery","banana");
/*另外一个对象FruitB*/
var FruitB={
n1:"apple",
n2:"orange"
};
/*FruitB对象调用FruitA构造函数的方法,将FruitA中change方法中的this指向了FruitB对象,并传入参数,*/
fruitA.change.call(FruitB,"pear","peach");
console.log(FruitB.n1); //输出 pear
console.log(FruitB.n2);// 输出 peach
解析:FruitB调用fruitA的change方法,将fruitA中的this绑定到对象FruitB上。
var name='张三';
function Person(name){
this.name=name;
this.sayName=function(){
setTimeout(function(){
console.log(this.name)
},2000)
};
this.sayNameBind=function(){
setTimeout(function(){
console.log(this.name)
}.bind(this),2000)
}
}
var person=new Person('李四');
person.sayName();//此时输出的是张三,因为setTimeout相当window.setTimeout,是window在调用这个方法,而window.name就是张三
person.sayNameBind();//此时输出的是李四,因为bind(this)调整了setTimeout中this的指向
解析:这里setTimeout(function(){console.log(this.name)}.bind(this),2000);,匿名函数使用bind(this)方法后创建了新的函数,这个新的函数不管在什么地方执行,this都指向的Person,而非window,因此最后的输出为"李四"而不是"张三",另外几个需要注意的地方setTimeout/setInterval/匿名函数执行的时候,this默认指向window对象,除非手动改变this的指向
5、箭头函数
function Timer() {
this.seconds = 0;
setInterval( () => this.seconds ++, 1000);
}
var timer = new Timer();
setTimeout( () => console.log(timer.seconds), 3100);
// 3
// 在构造函数内部的setInterval()内的回调函数,this始终指向实例化的对象,并获取实例化对象的seconds的属性,每1s这个属性的值都会增加1。否则最后在3s后执行setTimeOut()函数执行后输出的是0
解析:es6里面this指向固定化,始终指向外部对象,因为箭头函数没有this,因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向

浙公网安备 33010602011771号