第三章:实验室初探,谁动了我的this?
午饭过后,苏澈照例回到宿舍,简单收拾了书包就打算往实验楼走。大学里有一个对计算机专业学生开放的“项目实验室”,只要有兴趣,你可以去那里自由发挥自己的创意。
“大海,你要去吗?”
“去干啥?”赵大海正刷着游戏论坛,一脸迷惑。“你对实验室什么时候这么热衷了?那地方可是前端凹凸曼都不怎么去啊。”
“先不跟你解释。”苏澈摆摆手,“反正我有事要做,走了!”
他刚踏进实验室,就看见林雨菲坐在一台电脑前,似乎在研究什么项目。
“你也来了?”苏澈走近,笑着打了声招呼。
林雨菲回头看到他,有点惊讶:“你怎么知道这里?”
“以前虽然少来,但也不是没来过。”
林雨菲轻轻点头,她指着屏幕:“我在写一个小网页项目,用来展示课程笔记。结果发现一些交互逻辑跟预期不一样,好像是 this 指向出了问题。”
“this?”苏澈顿时来了兴趣。“不如让我看看?”
林雨菲把椅子让开,苏澈坐下仔细看了几眼代码。
var app = {
name: 'My Note App',
notes: [],
addNote: function(note) {
this.notes.push(note);
console.log('添加成功,notes 长度:' + this.notes.length);
}
};
var btn = document.getElementById('addBtn');
btn.addEventListener('click', function() {
// 这里的 this 是谁?
app.addNote('新笔记');
});
“看起来没啥问题啊?”林雨菲挠挠头。
苏澈笑了笑:“你再加个 console.log(this) 试试,就知道这里的 this 指向谁了。”
林雨菲照做,重新运行后,控制台输出:
添加成功,notes 长度:1
<button id="addBtn">...</button>
“果然,这里打印出来的 this 是那个按钮元素啊。”
林雨菲恍然大悟:“原来如此……是 addEventListener 的回调函数默认绑定了 this 到那个 DOM 元素上。”
苏澈点点头:“JavaScript 的 this 绑定确实坑多。像这种回调函数,如果你想让 this 指向 app,就得用 bind 或者箭头函数。”
他修改了代码:
btn.addEventListener('click', app.addNote.bind(app, '新笔记'));
或者:
btn.addEventListener('click', () => {
app.addNote('新笔记');
});
“这样就能确保调用 app.addNote 时,内部的 this 指向 app 本身了。”
林雨菲看完后,双眼一亮:“你讲得好清晰,比我自己摸索要强多了。”
“哪有,其实我也是多踩了几个坑才总结出来的。”苏澈故意谦虚。
就在这时,赵大海也推门而入,一副气喘吁吁的样子:“我说,你们俩干嘛不叫我?我一个人在宿舍玩游戏,连个队友都没有……”
说到这儿,他瞥见苏澈正在指点林雨菲写代码,顿时露出一种古怪的表情:“哟,这么快就开始双人组队啦?”
“别瞎说!”林雨菲俏脸一红,没好气地瞪了他一眼。
苏澈干咳两声:“咳,我们在研究 this 的绑定问题。”
“this?那玩意儿我知道啊,不就是表示当前对象嘛。”赵大海撇撇嘴,“不过有时候 this 也很迷,我写过一个 for 循环里调用方法的,结果指向完全乱套。”
“是指这样吗?”苏澈随手敲下一段代码示例:
var obj = {
data: [1, 2, 3],
print: function() {
this.data.forEach(function(item) {
console.log(this); // 这里的 this 是谁?
console.log(item);
});
}
};
obj.print();
赵大海看完,拍了拍脑门:“对对对,我就是这种情况!”
“forEach 的回调函数默认绑定到全局或 undefined(严格模式下)”,苏澈解释,“所以在这里,this 并不是 obj。要解决可以用箭头函数,或者再套一个 bind(obj)。”
“是哦……”赵大海一脸受教。
林雨菲笑着补充:“对了,箭头函数的 this 继承自外部作用域,所以就能一直指向 obj 了。”
赵大海伸了个懒腰:“哎,你们俩越说越专业,我都快跟不上了。”
苏澈合上笔记本:“哈哈,这只是开始。前端的深坑多了去了,这次只是让你们感受一下 this 绑定有多‘不讲武德’。”
林雨菲看了看时间:“要不,我们待会儿去吃个下午茶,然后回来继续?我还想研究下 class 语法糖,听说它本质上也是基于原型实现的,对吗?”
她转向苏澈,带着几分期待:“你会吗?”
“class ?当然。”苏澈笑得神秘,“别忘了,我可是一不小心从未来学来了全套。”
赵大海哼哼道:“你这口气,真像从异世界回来的勇者啊。”
“算你说对了。”苏澈耸肩,“咱们先补充点能量,一会儿我再教你们解锁更多新姿势。”
说完,三人一起离开实验室,朝校内小卖部走去。
在阳光的映照下,苏澈心里暖洋洋的。他能感觉到,自己在一点点地改变过去,也在为将来铺路。JavaScript 的“this” 只是一个开始,真正要迈向的目标,是那超越时代的 Vue 框架。