你怎么还没搞懂 this?

4个月前的那篇《this 的值到底是什么?一次说清楚 - 知乎专栏》已经把 this 的来龙去脉说清楚了,可以搞定面试遇到的所有相关题目。

不过实际项目中 this 的使用事情可能要更晦涩一点,我们就举例来说说。

本文用到的所有知识,依然来自《this 的值到底是什么?一次说清楚 - 知乎专栏》。


Event Handler 中的 this

btn.addEventListener('click' ,function handler(){
  console.log(this) // 请问这里的 this 是什么
})
handler 中的 this 是什么呀,看了你的文章我还是不懂啊?
那是因为你没有看懂,我们说过 this 都是由 call 或 apply 指定的,那么你只需要找到 handler 被调用时的代码就行了。
可是我哪知道 addEventListener 的源代码呀

是呀,addEventListener 是浏览器内置的方法,我们看不见源代码。

所以,你只能看文档了,MDN 这样说

通常来说this的值是触发事件的元素的引用,这种特性在多个相似的元素使用同一个通用事件监听器时非常让人满意。

当使用 addEventListener() 为一个元素注册事件的时候,句柄里的 this 值是该元素的引用。其与传递给句柄的 event 参数的 currentTarget 属性的值一样。

由于浏览器知道你不方便看源码里是怎么 call handler 的,所以直接在文档里告诉你了,你可以假想浏览器的源码是这样写的:

// 当事件被触发时
handler.call(event.currentTarget, event) 
// 那么 this 是什么不言而喻

jQuery Event Handler 中的 this

那么下面代码中的 this 是什么呢:

$ul.on('click', 'li' , function(){
  console.log(this)
})

同样,不要瞎猜,你要么看 jQuery 源码是怎么 call 这个函数的,要么看jQuery 文档

jQuery 文档是这样写的:

当jQuery的调用处理程序时,this关键字指向的是当前正在执行事件的元素。对于直接事件而言,this 代表绑定事件的元素。对于代理事件而言,this 则代表了与 selector 相匹配的元素。(注意,如果事件是从后代元素冒泡上来的话,那么 this 就有可能不等于 event.target。)若要使用 jQuery 的相关方法,可以根据当前元素创建一个 jQuery 对象,即使用 $(this)。

总结一下如何确定 this 是值

  1. 看源码中对应的函数是怎么被 call 的(这是最靠谱的办法)
  2. 看文档
  3. console.log(this)
  4. 不要瞎猜,你猜不到的

如何强制指定 this 的值?

自己写 call / apply 即可:

function handlerWrapper(event){
  function handler(){
    console.log(this) // 请问这里的 this 是什么
  }

  handler.call({name:'饥人谷'}, event)
}
btn.addEventListener('click', handlerWrapper)

你也可以直接使用 bind,与上面的代码效果差不多:

function handler(){
  console.log(this) // 请问这里的 this 是什么
}
var handlerWrapper = handler.bind({name:'饥人谷'})
btn.addEventListener('click', handlerWrapper)

上面三句代码可以挤成一句:

btn.addEventListener('click', function(){
  console.log(this) // 请问这里的 this 是什么
}.bind({name:'饥人谷'}))

这是前端里一个常见的套路。


this 不难,就看你有没有按照 call / apply 来理解函数了。

完。


P.S. 这是本周任务班直播里讲的内容

编辑于 2017-03-25

文章被以下专栏收录