之前写的this是关于this的基本知识,但遇到具体情境(不能看到具体call情况)又需要根据具体情境讨论
具体情境下如何确定 this 的值
- 看源码中对应的函数是怎么被 call 的(这是最靠谱的办法)
- 看文档
- console.log(this)
- 不要瞎猜,你猜不到的
Event Handler 中的 this
btn.addEventListener('click' ,function handler(){
console.log(this) // 请问这里的 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的调用处理程序时,this关键字指向的是当前正在执行事件的元素。对于直接事件而言,this 代表绑定事件的元素。对于代理事件而言,this 则代表了与 selector相匹配的元素。(注意,如果事件是从后代元素冒泡上来的话,那么 this 就有可能不等于 event.target。)若要使用 jQuery 的相关方法,可以根据当前元素创建一个 jQuery 对象,即使用 $(this)。
如何强制指定 this 的值?
自己写 call / apply 即可:
function handlerWrapper(event){
function handler(){
console.log(this) // 请问这里的 this 是什么
}
handler.call({name:'123'}, event)
}
btn.addEventListener('click', handlerWrapper)
你也可以直接使用 bind,与上面的代码效果差不多:
function handler(){
console.log(this) // 请问这里的 this 是什么
}
var handlerWrapper = handler.bind({name:'123'})
btn.addEventListener('click', handlerWrapper)
上面三句代码可以挤成一句:
btn.addEventListener('click', function(){
console.log(this) // 请问这里的 this 是什么
}.bind({name:'123'}))
这是前端里一个常见的套路。
答案都是:{name:'123'}