js中this的调用方式主要有以下几种。
普通函数调用
在这种情况下,属于全局性的调用,this就代表全局对象window。
// this指向的就是全局window,该方式相当于定义一个全局变量
function a () {
this.x = 1
console.log(this.x)
}
a(); // 1
// 将变量移到外面,调用结果一样
var x = 1
function a () {
console.log(this.x)
}
a(); // 1
作为方法调用
该种方法通过对象方法调用,这时this指向这个对象的上级,且具体指向由调用时来决定。
// 这里的this指向该对象,所以输出2
var x = 0;
var a = {
x: 1;
showX: function () {
console.log(this.name);
}
}
a.showX(); // 1
// 这里将a.showX赋值给全局变量,所以此时的this指向window
var m = a.showX;
m(); // 0
//虽然showX方法在a中定义,但是调用时候却是在b中调用,因此this指向b
var a = {
x: 1,
showX: function () {
console.log(this.x);
}
}
var b = {
x: 2,
showX: a.showX
}
b.showX(); // 2
作为构造函数调用
function A (x) {
this.x = x;
}
var a = new A();
a.x(1); // 1
call/apply方法调用
使用call/apply方法可以改变this的指向
var x = 0;
var a = {
x: 1,
showX: function () {
console.log(this.name);
}
}
a.showX.call(); // 0
bind方法调用
setTimeout/setInterval/匿名函数执行的时候,this默认指向window对象,除非手动改变this的指向。在《javascript高级程序设计》当中,写到:“超时调用的代码(setTimeout)都是在全局作用域中执行的,因此函数中的this的值,在非严格模式下是指向window对象,在严格模式下是指向undefined”
// 这里的setTimeout函数,相当于window.setTimeout(),此时this指向全局
var x = 0;
function A (x) {
this.x = x;
this.showX = function () {
setTimeout(function () {
console.log(this.x);
}, 50)
}
}
var a = new A(1);
a.showX(); // 0
// 通过bind()方法,绑定setTimeout里面的匿名函数this一直指向A
var x = 0;
function A (x) {
this.x = x;
this.showX = function () {
setTimeout(function () {
console.log(this.x);
}.bind(this), 50)
}
}
var a = new A(1);
a.showX(); // 1
箭头函数
es6里面this指向固定化,始终指向外部对象,因为箭头函数没有this,因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向
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