this在js高级程序设计这本书里面的定义是:this对象是在运行时基于函数的执行环境绑定的。
这里的环境分为4种:对象调用,全局函数调用,构造函数调用和用apply和call方法调用。
对象调用
作为对象的一个方法进行调用
var dog = {
name: 'x',
say () {
console.log(this.name)
}
}
全局函数调用
var a = 0;
function test () {
this.a = 1;
}
console.log(a) // 1
这种情况下你会发现this指向的其实是外部定义的a的全局变量。这个时候的this指向的其实是window对象。
在这里要说的是,当用函数表达式的时候,对象方法里面的this也会指向window对象
var dog = {
name: 'x',
say () {
console.log(this.name)
}
}
var cat = dog.say
cat () // undefined 这段代码中因为this指向了window,所以其实是查找window.name,全局并没有,所以是undefined
需要注意的是如果在严格模式下的话全局函数调用的时候,不会指向window,会是undefined;
构造函数中调用
在构造函数中调用的时候,this会指向新创建的对象。
var a = 0;
function Test () {
this.a = 1;
}
var test = new Test();
console.log(a) // 0
这是因为new操作符帮我们把this绑定到了对象上。
用apply和call的方法
这两个方法核心用法其实一样,都是改变this绑定的对象,区别在于apply传入的是一个参数数组,而call是分别传入参数,第一个参数都是要绑定的新对象,第二个参数是要传入的是要绑定的对象的属性。
var dog = {
name: 'x',
say () {
console.log(this.name)
}
};
var cat = {
name: 'y'
};
dog.say(); // x
dog.say.call() // window,如果不填参数,默认绑定window对象
dog.say.call(cat) // y
箭头函数里面的调用
这里还必须要提的就是在箭头函数里面的时候,this的定义是指向调用时的对象,但在箭头函数中不是,在箭头函数中,this指向的是函数定义时候所在作用域中的对象
var dog = {
name: 'x',
say () {
return function () {
console.log(this.name)
}
}
}
dog.say()() // undefined
但是如果改成箭头函数的话,就会指向对象中的属性
var dog = {
name: 'x',
say () {
return () => {
console.log(this.name)
}
}
}
dog.say()() // x
这种情况在一般es5中我们会定义一个变量来储存这个this,用来让this绑定对象
var dog = {
name: 'x',
say () {
var that = this
return function () {
console.log(that.name)
}
}
}
dog.say()() // x
这点需要注意。