这是javascript作用域系列文章,感兴趣的同学请保持关注。
this
我们几乎每天都在和this打交道,先不去管他的概念,看一个小栗子,预热一下
this初探
⚠️约定:
我们之前的一篇文章提到过,使用let和const声明的变量没有挂载到全局变量下,所以在全局下声明的变量我们使用var
var heroName = '黄蓉'
function hero() {
const heroName = "黄药师"
console.log(this)//window
console.log(this.heroName);//=>黄蓉
}
hero()
我们执行hero(),通过打印我们发现
this指向的是window全局,所以this.heroName,应当在全局下查找heroName,所以输出=>黄蓉
当全局下没有heroName呢?this指向的是全局,全局没有就是没有,那就是undefined
function hero() {
const heroName = "黄药师"
console.log(this)//window
console.log(this.heroName);//=>undefined
}
hero()
我们继续看一个栗子
var heroName = '黄蓉'
function hero() {
const heroName = "黄药师"
console.log(this)//oHero
console.log(this.heroName);//=>欧阳锋
}
const oHero={
heroName:'欧阳锋',
hero
}
oHero.hero()
提示:在声明oHero中的hero中,使用了ES6标准,当key和value同名是,可以像上面这样简写
上面的栗子中,调用hero()的环境变了 ,根据输出我们发现,this的指向变了
this的指向是oHero对象,所以this.heroName=>欧阳锋,同样的当oHero下没有heroName,毫无悬念,就会输出=>undefined
如果前面两个小栗子搞懂了,我们就继续
一个栗子
var heroName = '黄蓉'
function hero() {
console.log(this.heroName);
}
const oHero1 = {
heroName:'郭靖',
hero
};
hero()//=>黄蓉
oHero1.hero()//=>郭靖
现在我们尝试着给this下一个定义:
this指的是函数运行时所在的环境,如果一个函数内部有this,this就会指向一个对象,指向哪个对象呢?取决于这个函数的执行环境。
补充(如果在全局下调用这个函数,则this指向全局,如果在某个对象下调用this,则this指向这个对象)
能看到这里,说明你很聪明,哇,this这么easy吗?
this并没有那么简单
再看一个栗子
var heroName = '黄蓉'
function hero1() {
const heroName = "黄药师"
this.hero2()
}
function hero2() {
console.log(this.heroName);
}
hero1()
先不关心输出
我们在hero2中的console.log前加一个debugger,分别看下两个this的指向
可以发现。两个this均指向window
在脑中跑一遍这段代码,希望你还清醒
我们一起捋一下:
全局下执行hero1()
在hero1中,this指向的是全局=>window, 全局下存在hero2(),
在hero2中,this指向哪里?取决于是哪里调用的hero2(),是在hero1()中调用的hero2(),
所以hero2中的this指向hero1?输出=>黄药师?
但是我们通过debugger得出,hero2中的this指向的是window,所以输出必然是=>黄蓉
为什么呢?
我们再看一个栗子
function hero(){
console.log(this.heroName);
}
var HERO1 = {
heroName : '黄蓉',
hero
}
var HERO2 = {
heroName : '郭靖',
HERO1
}
var HERO3 = {
heroName : '郭靖',
HERO2
}
HERO3.HERO2.HERO1.hero()//=>黄蓉
我相信不会有人写出这样的代码,除了我!
这依然是个调用链
我们在输出前打一个断点
this指向了谁?不是最初的调用方HERO3,而是上一次,或者所最后一次=>HERO1
this似乎也不难
出现上面这种情况,是由函数调用方式决定的
- 作为一个函数进行的调用
- 作为一个对象的方法进行的调用
3. 作为构造器进行的调用
4. 通过apply()、call()函数进行的调用
后面两个暂不做讨论
作为一个函数调用this指向window,作为一个对象的方法调用,this指向当前调用的对象
回顾之前的栗子
var heroName = '黄蓉'
function hero() {
console.log(this.heroName);
}
const oHero1 = {
heroName:'郭靖',
hero
};
hero()//=>黄蓉
oHero1.hero()//=>郭靖
hero(),是作为一个函数进行调用的,所以this指向window
oHero1.hero(), 是作为一个函数的方法调用的,所以this指向oHero1对象
继续看一个栗子
function hero1(){
this.hero2()
}
function hero2(){
console.log(this.heroName);//Uncaught TypeError: this.hero2 is not a function
}
var HERO1 = {
heroName : '黄蓉',
hero1
}
var HERO2 = {
heroName : '郭靖',
HERO1
}
HERO2.HERO1.hero1()
报错了
HERO1对象下调用的hero1(),所以hero1()中this指向的是HERO1,但是HERO1中不存在方法hero2(),所以报错
稍作修改
function hero1(){
HERO3.hero2()
}
function hero2(){
console.log(this.heroName);//=>郭靖
}
var HERO1 = {
heroName : '黄蓉',
hero1
}
var HERO2 = {
heroName : '郭靖',
HERO1
}
var HERO3 = {
heroName : '郭靖',
hero2
}
HERO2.HERO1.hero1()
我们似乎总结出来一点小窍门,我们从最后的输出反推执行顺序
是谁调用的hero2(),是HERO3,所以hero2,中的this指向HERO3,所以输出是=>郭靖
啊?this好简单?真的吗?关于下次的讨论,敬请期待
END
最新评论
这小生活不错呀
不错,必须顶一下!
看着你还在坚持,很好
看来忙了也没时间更新博客了
NIce。学习了。。。。
网站不错!!!!
简洁实用,好文章!
不错,过来支持一下