第三章:实验室初探,谁动了我的this?

107 阅读4分钟

第三章:实验室初探,谁动了我的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 框架。