深入理解 JS 中的 this

在 JavaScript 中 this 是在函数运行时内部自动创建的一个对象,作为执行上下文的一个重要属性,它会随着执行环境的变化而改变。
那么首先来看一下 this 的几种用法。
this 的几种用法
单独使用,this 表示全局对象
在函数中使用,this 表示全局对象
在对象方法中使用,this 表示该方法所属的对象
在构造函数中使用,this 指向实例化后的新对象
在事件方法中使用,this 指向接收事件的元素
通过 call 或 apply 改变 this 指向,指向传入的第一个参数
this 的实现原理
接下来再看一个例子:
此时我们发现 obj.foo()
和把 obj.foo
赋给一个新变量后的执行结果并不一样,我们知道是 this 的指向发生了改变,但是发生改变的原因是什么呢?这个可以从 JS 在内存中的存储结构说起。
来看一下上面代码中对象 obj 的存储结构:

a
没什么可说的,作为基本类型直接存储在栈内存中,而函数 foo 作为一个引用类型,在栈空间中存储的只是一个指针,指向了堆空间实际的存储地址。
那么函数作为一个单独的值,可以在不同的上下文中执行,引用阮老师的话就是:
由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this 就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。
因此,当执行 obj.foo()
时,函数 foo 是在 obj 环境中运行的,即 this.a
等价于 obj.a
。
而当 obj.foo
复制给 bar 时,对象 obj 及变量 bar 的内存结构是这样的:

从图中可以看出,变量 bar 和 obj.foo 指向的是同一个地址,但是它们的执行环境却不同,当 bar 执行时,bar 的执行环境是在全局上下文中,因此输出 a 的值为 2
相关参考:
Photo by Pete Walls on Unsplash
版权声明: 本文为 InfoQ 作者【Verlime】的原创文章。
原文链接:【http://xie.infoq.cn/article/aa888a6fef041b103022e9bbd】。文章转载请联系作者。
评论