「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」
不知道小伙伴们有没有这样的疑问。this是个关键字? this.this为什么不指向自己?
答: this 的确是个关键字,不是什么全局对象,也不是内置属性,只不过一般会指向某个对象。
然后,this.this === undefined。
this.this
一般人肯定也不会这样想,也就更不会这样写了。
一开始我也没有这么想过。 直到某天,有个小伙伴甲在群里问,他的vue语法有没有什么问题,怎么不起作用,还说了他的期望云云。我一眼就看到了 类似这样的写法<p>{{this.msg}}</p>
,先不管,他其他有啥错。就这个,我就立马指出来了, 甲,你怎么又在模板里写this,上次不是跟你说过了吗?.....
但是甲毫无知觉地问道,这样有啥问题吗? 我心想,是时候让你知道vue的模板语法是要经过编译的, 所有绑定语法和小胡子语法,里面写的标识符都会去当前组件的对应属性方法上找。 这也是为啥不能在模板里使用 Date Math ParseInt等一些全局对象和方法.
但是我表达能力有限,甲似乎并不明白, 我就直接说,你在img的src上绑定一个路径url ,被编译之后就是this.url ,但是你写的是this.url,那么编译后,就是this.this.url.
甲恍然大悟,并发誓下次一定注意。 呵呵,还有下次?
不过我也有点好奇,于是打印了一下 this.this . 结果自然是 undefined
作用域链 和 原型链
作用域链,当前词法环境闭包里面没有,就会去外面找。那么为啥this.this 是undefined,为啥不能在模板写全局方法和属性,不能顺着作用域链往外找到吗?
当然不能,作用域链的查找机制,是用来查找标识符,限于表层的。
比如 要访问 a.b,首先会在当前作用域查找 a 这个变量,没有就往外继续, 直到找到为止。
作用域链查找完毕,原型链差不多该登场了。假设a找到了, 要访问a.b,也就是要访问a上面的b属性。如果实例a上面没有这个属性b,那么就会去a的原型上找a.__proto__.b
, 如果没有继续往源头找·······
如此一来,我们想访问this.this的时候,首先找到this,这个就不多说了,构造函数指向实例,函数内部,谁调用就指向谁,还有call apply bind, 没有明确指向就是全局globalThis. (以上所说在非严格模式下适用)
根据上述规则就找到了this,然后就是找this实例上的this属性,如果当前上下文上没有这个属性,那么去它的原型上找······
但是, 经过了一阵查找,在Object.prototype上也没有找到
,查无此属性,于是返回undefined。
this.this 第一个this是关键字,第二个就是一个属性名,可不是什么关键字了。
最后
访问一个变量,首先是找到一级的标识符,通过作用域链来查找,找到a.b的a ,
如果是要访问它下面的属性,那么接下来,原型链就登场了。
注意到开头的图片了吗。虽然this.this不会循环,但是window.window 会。
我也有点费解,如果有知道的小伙伴,还望不吝赐教。