在javascript中绝大多数情况下,函数的调用方式决定了this的值,也就是说this指向调用者
- 普通函数

结果很显然,没什么好说的,通过变量a.出来,此时的this指向的当然是a(全局的那个a)



如果将函数b从a中解构出来,那么再去调用函数b,此时调用者是全局对象window,所以打印出的结果就是全局变量a
注意:但是这里并不能认为是执行了window.b()这个操作才使得this指向了window的,原因就在这个let,后面会说明
- 箭头函数
箭头函数是es6中的新特性,不仅提供了简洁的函数书写方式,最关键的是箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this,也就是说箭头函数中this指向定义者


此时的this在定义时就已经被安排得明明白白了,或许会有疑问,为什么定义他的不是a这个obj,而是window,其实这个“定义者”的含义不太准确,
ES6中定义的时候绑定this的具体含义,应该继承的是父执行上下文里面的this,而简单对象(非函数)是没有执行上下文的,所以箭头函数里的this没有绑定obj,自然而然是绑定到window对象上了
继承父执行上下文里面的this,的意思就是定义这个箭头函数的‘父亲’的this是什么,那箭头函数中的this就是什么


现将b函数这样定义,在箭头函数的外层再套一层匿名函数,按照刚才的说法,此时箭头函数的this就继承于这个匿名函数的this,而匿名函数(普通函数)的this又跟调用方式有关,是指向调用者的
所以执行a.b()(),此时通过a.找到函数b,再调用,匿名函数的this就指向a,而箭头函数的this是一直指向匿名函数的this的,所以执行结果为1


把b从a中解构出来,直接调用b函数的执行结果,此时是window在调用函数b,那么匿名函数的this指向调用者window,箭头函数的this还是指向匿名函数,所以执行结果为全局a
当理解了this在普通函数和箭头函数的指向后,我们再看这个例子


函数b:箭头函数this指向“父亲”的this,这里“父亲”是外层函数a,此时是window调用的a,所以a的this指向window
b的this->a的this->window
函数c:普通函数指向执行者,这里虽然是在a中执行的c,但是执行者还是window,所以c的this指向window


具体解析就不说了,其实只要弄懂了函数的执行上下文和调用方式,分析再复杂的嵌套调用都不是什么难题,管你有多花里胡哨的调用,都不难
当完全理解了this之后,再回过头看之前跟let、const有关的问题

很眼熟?但是答案或许让你很失望,执行结果是undefined
其实这里的代码本身没有什么问题,关键就是,这个代码的位置
<script>
...
</script>
该代码在任何一个代码块中运行结果就是如你所料的123,但是我把它放到了<script>标签中情况就变得不一样了
我们都知道const,let是定义在块级作用域的,在<script>标签中使用const,let定义的变量,并不会在全局global对象中出现,而是会出现在sciprt里面

可以看到,以const定义的a并未出现在global中
再来看看,当我们以var定义a时

a出现在了global中,此时执行结果也会是a这个obj{}
所以在前文中提到的let问题也就能说明了,将b从a中解构出来并执行b(),虽然是window直接调用的函数b,但是并不等于执行window.b(),因为此时window中根本没有b这个函数,因为我是用let定义的函数b