this是JavaScript语言的一个关键字。它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。
由于函数运行时环境不同,this的值也会随之变化。接下来通过几种情况讲解一下this的指向(暂不讨论严格模式下)。
一、全局环境
this指向全局对象window
。注意严格模式下,普通函数里的this为undefined
。
console.log(this); // Window
function test() {
console.log(this); //Window
}
test(); // 相对于window.test()
二、对象方法中
this指向调用该方法的对象。
var name = 'ldj';
var obj = {
name: 'obj',
getName: function () {
console.log(this.name);
}
}
obj.getName(); // obj
let fn = obj.getName; // 将这个函数赋值给变量fn
fn(); // ldj 解析:因为此时的fn相对于window对象调用的,所以输出的name是最开始定义的那个
三、构造函数中
this指向创建出的实例。
function demo() {
this.name = 'demo';
console.log(this);
}
let a = new demo(); // 构造一个demo的实例对象
console.log(a.name); // demo
注意:如果构造函数返回了一个对象,则this指向这个返回的对象。
即如果返回值是一个对象,那么this指向的就是那个返回的对象;如果返回值不是一个对象那么this还是指向函数的实例。
function Fn() {
this.name = "ldj";
return {};
// return function () { }; // 返回一个函数也同理,因为函数也是特殊的对象
}
var a = new Fn;
console.log(a.name); // undefined
console.log(a); // {}
function Fn() {
this.name = 'ldj';
return 1;
// return undefined; // 同理
// return null; // 虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊。
}
var c = new Fn3;
console.log(c.user); //ldj
四、setTimeout 和 setInterval 中
定时器函数内部的回调函数的this指向window,但是我们可以通过bind方法或者使用箭头函数改变this指向。
setTimeout(() => {
console.log(this); //Window,严格模式下也是指向window
}, 500);
// bind方法改变
function Person() {
this.age = 18;
setTimeout((function () {
console.log(this);
}).bind(this), 500);
}
var p = new Person(); // Person{...}
// 箭头函数改变
var obj = {
name : 'obj',
fn: function(){
setTimeout(() => {
console.log(this.name);
}, 500)
}
}
obj.fn(); // obj
五、箭头函数
箭头函数本身没有自己的this,它的this指向箭头函数定义时所处的对象,而非调用时所在的对象。
var obj = {
fn: function () {
console.log(this);
},
fn2: () => {
console.log(this); // 因为fn2只是obj的一个属性,而obj定义在window下,所以这个箭头函数的this是window。
}
}
obj.fn(); // obj
obj.fn2(); // Window
总结
- 在普通函数中,它的this取决于谁调用了这个函数。
- 在箭头函数中,它的this取决于函数定义在哪里。
- 在构造函数中,如果构造函数没有返回值或者返回值不是对象时,它的this指向了创建的实例对象;如果构造函数返回了一个对象,则this指向这个返回的对象。
- 在回调函数中,它的this默认指向window。
- 在定时器中,this一般指向window对象,但是我们可以通过bind、apply方法或使用箭头函数做回调函数去改变this的指向。