学过Javascript的同学一定被this搞得头晕脑胀过,我自己也困惑了好久,一下指向全局,一下指向对象,一下又指向undefined,如果不了解this的特性以及绑定规则的话,你之后学Javascript只会越来越困惑,这里我特意去整理了一下比较全面的this特性以及绑定规则,希望能帮助到你。
为什么需要this
const obj = {
name: 'zengge',
age: 22,
eating(){
console.log(`${this.name}在吃东西`)
},
running(){
console.log(`${this.age}的${this.name}在吃东西`)
},
}
上图的代码this.name和this.age能不能用直接用obj代替呢?答案是可以的。这样看来从某些角度上来说,开发中并不需要用到this,完全可以直接用当前的对象代替this啊,那为什么还要用this呢?好的,那么如果说这个对象里有1000个方法,每个方法都用到了对象中的属性,有一天我们需要改变这个对象的名字,那么我们要一个一个去修改这1000个方法中的obj属性名吗?所以没有this是可以的,但是有了this可以大大增加开发和维护的效率,这就是this在Javascript中存在的意义。
全局作用域中的this
在大多数情况下,this都是出现在对象或者函数中,但是在浏览器或者全局中this指向的就是window对象。
而在node中,this指向的是一个空对象。
我们开发中很少会在全局下去使用this,一般都是在函数或者对象中使用。那么如果在函数中使用了this,它的绑定规则又是什么呢?
function foo() {
console.log(this)
}
foo()
const obj = {
foo,
}
obj.foo()
foo.apply('123')
这三个函数调用分别打印什么?结果会是一样吗?
显然,结果并不一样。由此可知,函数中的this指向跟函数所处的位置无关,而是跟函数被调用的方式有关。第一个foo函数被调用是在全局中被调用,所以this指向的是全局window。第二个函数存在于obj对象中而且被obj对象调用,所以this指向obj对象本身。第三个函数经过了apply函数调用,改变了this原本的指向,从而指向了内置的String类。事实上,this的绑定总共有四种,只要掌握了这四种绑定规则,就真正掌握住this的使用。
四种this绑定规则
- 默认绑定
- 隐式绑定
- 显式绑定
- new绑定
默认绑定
什么情况下是默认绑定呢?就是当一个函数独立调用时,也就是说可以理解成函数没有被绑定到某个对象中进行调用,此时的this就会绑定到当前全局作用域(不一定是window)。
案例一
function foo() {
console.log(this)
}
function foo2() {
console.log(this)
foo()
}
function foo3() {
console.log(this)
foo2()
}
foo3()
想想这三个this分别打印什么,没错,就是你想的那样,三个都是打印window对象。
如果你觉得简单我们来看看下面的案例:
案例二
const obj = {
name: 'zengge',
foo(){
console.log(this)
}
}
const objFunc = obj.foo
objFunc()
这个案例我估计会有不少同学会掉陷阱了。你会说哎这个不是上面说过的么,你看foo函数在obj对象里,那执行这个foo函数里面的this不是指向obj对象本身吗?如果这样想那你就掉坑喽。我们上面说过this在函数中的指向跟函数的位置无关,而跟函数的调用方式有关。我们这里的objFunc指向的是foo函数没错,但是objFunc函数是独立调用的,并没有说是通过某个对象以点的方式调用的。所以说符合默认绑定规则,函数中的this指向全局,而这里的全局就是指向window对象。
隐式绑定
隐式绑定指的是被绑定到某个对象中的函数通过对象点的方式调用,此时的this就会隐式地绑定到该对象上。我们还是拿之前的代码举例:
案例一
function foo() {
console.log(this)
}
const obj = {
foo,
}
obj.foo()
这里为什么打印的是
foo对象呢?注意这里的foo函数是被obj.的方式调用的,这个时候js引擎就会将foo函数中的this绑定到foo对象了。
案例二
const obj1 = {
name: 'zengge',
foo(){
console.log(this)
}
}
const obj2 = {
name: 'zengge2',
bar:obj1.foo
}
obj2.bar()
那么这里的obj2.bar函数执行打印的又是什么呢?是obj1对象吗?还是window对象呢?都不是,结果是obj2对象。
这应该很好理解了,上面说了隐式绑定的规则了,bar函数在此处并不是独立调用,而是通过obj2.的方式调用,所以this隐式地被绑定给了obj2对象。
好了今天就先总结两种绑定规则,明天总结后面两种,记得好好阅读文章哦。