作为一名实战前端工程师,在jq时代,是经常被this关键字难倒的。几年前每次我意识到程序出现问题的时候,都本能反应是自己的this没有绑定好,于是重新绑定一下,就能解决了。但是他确实一直为难着我。
转眼到了2022年底,我想需要解决一下这个千年难题了。于是我开始认真摸索一番。
到底什么是this
简单说,this就是属性或方法“当前”所在的对象。
为什么这么简单的定义,我们理解不了?
- 层层嵌套,改变了this对象
- 对象自动携带this,或者全局默认有this对象
- 操作dom的时候,this对象变得扑朔迷离。
实际上JavaScript 的变量类型一样,看看这三种类型的变量,是不是更容易理解this了?
局部变量
被捕获变量
全局变量
this的实质
JavaScript 的对象类型存放给变量的是一个引用地址,是一个字符串地址。
变量o是一个地址(reference)。后面如果要读取o.obj,引擎先从o拿到内存地址,然后再从该地址读出原始的对象,返回它的obj属性。
到这里好像跟this没关系?回忆一下,我们第一次接触this是学什么知识点的时候?没错,构造函数,new一个对象的时候,实例对象默认创建了this变量,这是我们第一次学习到this关键字。
我们把上面的对象o上加入kill方法.
var o = {
num: 1,
obj:{a:1},
kill: function(){
console.log(this.num)
}
}
现在问题就来了,调用o.kill()
会输出什么?
如果var b = o.kill; b();又输出什么?
答案是o.kill()
会输出1;而b()又输出的是undefined。 为什么产生这样的不同呢?
由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
o.kill()
的运行上下文是o这个对象(往上看一下哪个对象引用地址图);而b变量的运行上下文是window全局。b是window对象下的一个变量,所以b是在window对象包裹内部,而window对象其他地方没有定义num变量,所以num就是未定义。