--外功篇-《JavaScript那些事》-01-理解This指向--
功法小传
近日的小虾米,在研习JavaScript招式的过程中,博采众长,勤奋练习,翻阅古籍。
终了然JavaScript招式中,容易引人走火入魔的变数之一——this指向!
虽不敢说完全了然,但其基本理解,心中有数。
对日后行走江湖,多有裨益。
于是,匆匆记下,以备后事之需:
内容正传
JavaScript的this指向问题:
在我们使用JavaScript操作dom时,经常会使用this来引用当前对象。但有时候,往往预料之中的指向却出现个指向错误的问题。
近日,小虾米翻阅了《你不知道的JavaScript》这本书,对其中的this讲解做一个总结和笔记吧。
调用栈
首先需要明白,JavaScript的调用栈的概念。
function three() {
console.log("three has done!")
}
function two() {
three();
console.log("two has done!")
}
function one() {
two();
console.log("one has done!")
}
one();
//输出:
// three has done!
// two has done!
// one has done!
在这个代码片段中,我们通过one进行了one->two->three的调用。
由输出可以知道,先进入调用栈的函数最后执行。
this的执行方式
this并不是在函数声明时执行的,而是在函数运行中才执行。
因此,this的指向就与this所处的函数以及函数的状态有关。
this指向的判断
上文中提到“this所处的函数以及函数的状态”,就是传说中的“上下文”。
这么解释起来还是有些抽象。
举个代码例子:
1.
var val = 2;
function a() {
console.log(this.val);
}
a();
//输出:
// undefined
这个代码片段中的this指向的是全局,因为a函数所处于全局环境中;
2.
function a() {
console.log(this.val);
}
var obj = {
val: 1,
a: a
}
obj.a();
// 输出:
// 1
这个代码片段中的this指向的是obj,因为a函数所处于obj对象的环境中;
这里,我们就已经解决完一般函数中的this指向问题了。
但要注意,在连续对象嵌套中(如:obj1().obj2().a()),this只会指向他调用栈的前一位对象(例子中只会指向obj2)
PS:有人会将“上下文”理解为this作用时其所处的对象作用域中。这种理解在大部分情况下是这样,但在JavaScript底层的运行过程中并不是如此。
有关this的隐式绑定
this绑定中,还存在一下代码片段的问题:
obj = {
val: 1,
a: function() {
console.log(this.val);
}
}
function fnc(fn) {
fn();
}
fnc(obj.a);
// 输出:
// undefined
看到这里肯定会疑惑,a明明是所处于对象obj中的,为什么输出的是undefined这个全局环境才有的结果呢?
记得this的执行原理嘛?this是在代码运行时进行指向。
fnc在执行时,是将obj中的a函数,作为fnc的形参传入fnc中,因此,this的指向与fnc所处环境有关,而与obj无关了。
这就是this的隐式绑定。
关于new绑定和硬绑定
在JavaScript中,我们经常使用new来进行构造函数的实例化,这个过程也是创建了对象,其实例化对象的this指向与之前所讲的对象中的this指向没什么区别
关于硬绑定,是我们使用call、apply、bind进行this强制指向传入对象的方法,来达成我们需要this指向特定对象的目的。
补充:
PS:记录至此,若日后还有补充,则另开篇再记录~