转载自martin的博客
最近在写程序的时候,一直有一个疑问,就是事件处理函数在绑定之后,该事件绑定的回调函数的this的指向以及该函数可以访问的作用域是怎么样的 。今天有空做了一下测试,总结一下:
1. 事件处理函数绑定之后,this指向该事件绑定的元素。
2. 事件处理函数可以访问的作用域:包括了该绑定发生时的上下文。
this的测试
这个测试很简单,写一个html代码对this进行输出就可以验证this的指向。我的测试代码如下。body onload触发init函数,对body绑定了onclick函数,该函数输出this的值,结果表明输出的就是body节点。所以在事件处理函数中,this指向绑定的元素,当然,用bind是可以修改this的指向。
<html>
<head>
<meta charset="utf-8">
</head>
<body onload = 'init()'>
<p>给body绑定了onclick事件</p>
<p>点击body</p>
<p>在控制台输出this的值</p>
<script>
var obj = {
name:'xiaobo',
age:'23'
};
function init() {
document.body.onclick = function() {
console.log(this)//body
};
}
// function init() {
// document.body.onclick = function() {
// console.log(this)//obj
// }.bind(obj);
// }
</script>
</body>
</html>
作用域测试
在js中,函数的作用域往往是内部的函数可以访问外部函数的作用域,而外部的函数无法访问内部的作用域,能够访问外部函数作用域的函数也成为闭包。事件绑定操作有DOM2,DOM0,IE的方法,不论用哪种方法,都可以进行绑定,我的疑问在于绑定的事件处理函数,它的作用域是哪里,能不能访问外部函数的作用域。为了了解这一点,我做了下面这个测试。
<html>
<head>
<meta charset="utf-8">
</head>
<body onload = 'init()'>
<p>给body绑定了onclick事件</p>
<p>点击body</p>
<p>在控制台输出this的值</p>
<script>
var obj = {
name:'xiaobo',
age:'23'
};
function init() {
var obj2 = {
name:'xiaobo2',
age:'25'
}
document.body.onclick = function() {
console.log(obj2);//obj2
console.log(obj);//obj
};
}
// function init() {
// document.body.onclick = function() {
// console.log(this)
// }.bind(obj);
// }
</script>
</body>
</html>
在上述代码中,body.onclick的事件处理函数,输出了init函数中定义的obj2,全局定义的obj,均能进行输出,证明onclick的回调函数继承了事件绑定的上下文,也就是事件处理函数(回调函数)能够拥有事件绑定的时候的上下文(本例中,事件是在init函数中进行绑定,所以回调函数继承了init这个作用域,能够访问到obj2)同时,Init本身也是定义在全局中,所以回调函数也可以访问到全局作用域。
总结
通过这两个测试,可以很明显的看出来this的指向以及上下文的继承,虽然在上面只列出了采用DOM0进行事件绑定的例子,但是DOM2的事件回调中this和上下文的继承关系都是这样的,IE中没有进行测试。IE嘛。。。