首先this不是指向自身!this就是一个指针,指向调用函数的对象.为了可以一眼看出this指向的是什么,我们需要知道this的绑定规则有哪些?
- 默认绑定
- 隐式绑定
- 硬绑定
- new 绑定
默认绑定
在不能应用其他绑定规则时使用的默认规则,通常是独立函数调用
function sayHi() {
console.log('hello',this.name)
}
let name = 'YvetteLau';
sayHi(); // hello YvutteLau(浏览器环境下)
在调用sayHi时,应用了默认绑定,this指向的是全局对象(非严格模式下),严格模式下指向的是undefined,undefined下没有this,会报错
上述代码,如果在浏览器环境下运行,输出的是 hello YvutteLau,但是如果实在node环境下,输出的是 hello undefinded,这是因为node中name并不是挂在全局对象下面的,下文如无特别说明,一律默认是在浏览器环境下
隐式绑定
函数的调用是在某个对象上触发的,即调用位置存在上下文关系.典型的形式为 xxx.func()
function sayHi() {
console.log('hello',this.name)
}
let person = {
name:'YvutteLau',
sayHi:sayHi
}
person.sayHi(); // hello YvutteLau
sayHi函数声明在外部,严格来说并不属于person,但是在调用sayHi时,会使用person的上下文来引用函数,隐式绑定会把函数中的this绑定到这个上下文对象(即person对象)
需要注意的是,对象属性链中只有最后一层会影响到this的调用关系
function sayHi() {
console.log('hello', this.name)
}
let person1 = {
name:'Christina',
sayHi:sayHi
}
let person2 = {
name:'YvutteLau',
friend:person1
}
person2.friend.sayHi(); // hello, Christina
不管有多少层,在判断this的时候,我们只关注最后一层,因为只有最后一层才能决定this指向的是什么
隐式绑定有一个很大的缺陷,绑定很容易丢失
function sayHi() {
console.log('hello',this.name);
}
var person = {
name:'Christina',
sayHi:sayHi
}
var name = 'Wiliam';
var hi = person.sayHi();
hi(); // hello,Wiliam;
除了上面这种丢失之外,隐式绑定的丢失发生在回调函数中,事件回调也是其中一种(原谅我理解不了)
function sayHi(){
console.log('Hello,', this.name);
}
var person1 = {
name: 'YvetteLau',
sayHi: function(){
setTimeout(function(){
console.log('Hello,',this.name);
})
}
}
var person2 = {
name: 'Christina',
sayHi: sayHi
}
var name='Wiliam';
person1.sayHi();
setTimeout(person2.sayHi,100);
setTimeout(function(){
person2.sayHi();
},200);
显示绑定
显示绑定比较好理解,就是通过call,apply,bind的方式,显示的绑定this所指向的对象(《你不知道的JavaScript》中将bind单独作为硬绑定讲解了)
call,apply,bind的第一个参数,就是对应函数的this所指向的对象.call和apply的作用一样,只是传参方式不一样.call和apply都会执行对应的函数,而bind不会
function sayHi() {
console.log('hello',this.name);
}
var person = {
name:'Christina',
sayHi:sayHi
}
var name = 'Wiliam';
var hi = person.sayHi;
hi.call(person);
原文摘自 嗨,你不知道的this 还有