关于事件处理函数的参数问题以及this绑定

时间:2022-12-20 08:34:20
下面一段代码是cloudgamer的JavaScript简易拖放效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>简易拖放效果</title>
</head>

<body>


<script>

var isIE = (document.all) ? true : false;

var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};

var Class = {
create: function() {
return function() { this.initialize.apply(this, arguments); }
}
}

var Extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
}

var Bind = function(object, fun) {
return function() {
return fun.apply(object, arguments);
}
}

var BindAsEventListener = function(object, fun) {
return function(event) {
return fun.call(object, (event || window.event));
}
}

function addEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.addEventListener) {
oTarget.addEventListener(sEventType, fnHandler, false);
} else if (oTarget.attachEvent) {
oTarget.attachEvent("on" + sEventType, fnHandler);
} else {
oTarget["on" + sEventType] = fnHandler;
}
};

function removeEventHandler(oTarget, sEventType, fnHandler) {
    if (oTarget.removeEventListener) {
        oTarget.removeEventListener(sEventType, fnHandler, false);
    } else if (oTarget.detachEvent) {
        oTarget.detachEvent("on" + sEventType, fnHandler);
    } else { 
        oTarget["on" + sEventType] = null;
    }
};

//拖放程序
var SimpleDrag = Class.create();
SimpleDrag.prototype = {
  //拖放对象,触发对象
  initialize: function(drag) {
this.Drag = $(drag);
this._x = this._y = 0;
this._fM = BindAsEventListener(this, this.Move);
this._fS = Bind(this, this.Stop);
this.Drag.style.position = "absolute";
addEventHandler(this.Drag, "mousedown", BindAsEventListener(this, this.Start));
  },
  //准备拖动
  Start: function(oEvent) {
this._x = oEvent.clientX - this.Drag.offsetLeft;
this._y = oEvent.clientY - this.Drag.offsetTop;
addEventHandler(document, "mousemove", this._fM);
addEventHandler(document, "mouseup", this._fS);
  },
  //拖动
  Move: function(oEvent) {
this.Drag.style.left = oEvent.clientX - this._x + "px";
this.Drag.style.top = oEvent.clientY - this._y + "px";
  },
  //停止拖动
  Stop: function() {
removeEventHandler(document, "mousemove", this._fM);
removeEventHandler(document, "mouseup", this._fS);
  }
};

</script>

<div id="idDrag" style="border:5px solid #0000FF; background:#C4E3FD; width:50px; height:50px;"></div>

<script>
new SimpleDrag("idDrag");
</script>

</body>
</html>


然后我将initialize改成:

initialize: function(drag) {
this.Drag = $(drag);
this._x = this._y = 0;
this._fM = Bind(this, this.Move);
this._fS = Bind(this, this.Stop);
this.Drag.style.position = "absolute";
addEventHandler(this.Drag, "mousedown", Bind(this, this.Start));
  },

不用BindAsEventListener了,用Bind。本以为这样改动后,在IE下是无法拖动的,结果是正常运行。 就这个问题求解!
我的理解是:
使用Bind(this, this.Start),事件触发的时候就直接执行Start(oEvent)。如果是FF,由于是DOM事件模型,那么事件发生时,系统会自动给该函数的第一个参数传入一个Event对象,也就是说oEvent就是event对象。但是如果是IE的话,事件发生不会给函数传递event对象,要使用window.event获取。这也正是BindAsEventListener做的,传入了正确的event。
可是事实是,FF和IE都能运行。
另个问题:
这里用BindAsEventListener和Bind来绑定this,本质是通过call和apply去修改this。这里不绑定,那么Move和Start里面的this指向就肯定出错。那么都有哪些地方需要绑定this?有没有精确点的总结和分析?

6 个解决方案

#1


该回复于2011-01-12 14:25:50被版主删除

#2


document.getElementById('sss').attachEvent('onclick',function(e){
alert(e.type);
})
测试的是,这个在IE5.5下都可以弹出event.type。
也就是说attachEvent可以传入Event对象。
但是this指向的是window。

htmlElement.onclick = function(e){}IE就不能传入Event对象了,而this指向的是htmlElement。

#3


引用 2 楼 crazywa 的回复:
document.getElementById('sss').attachEvent('onclick',function(e){
alert(e.type);
})
测试的是,这个在IE5.5下都可以弹出event.type。
也就是说attachEvent可以传入Event对象。
但是this指向的是window。

htmlElement.onclick = functio……

就像你说的,事实就是:attachEvent可以传入Event对象。我贴的例子也说明了这个,但是我记得attachEvent的事件函数不该可以传Event对象的啊?
下面是我做的小测试。

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
window.onload=function()
{
var redObj=document.getElementById("red");
redObj.attachEvent("onclick",clickHandle);
redObj.attachEvent("onmouseout",mouseoutHandle("mouseout"));
}
function clickHandle()
{
try{
alert(arguments[0].type);
}catch(e){
alert(e.name+":"+e.message);
}
}
function mouseoutHandle(type)
{
return function(){
alert(type);
alert(arguments.length);
};
}
</script>
</head>
<body>
  <div id="red" style="width:50px;height:50px;background-color:red"></div>
  <div id="black" style="width:50px;height:50px;background-color:black" onclick="clickHandle()"></div>
</body>
</html>

欢迎讨论啊,疑惑着呢,还有关于this绑定,散分。

#4


该回复于2011-01-12 17:36:35被版主删除

#5


行,那我把你的demo修改下 你再看看

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
window.onload=function()
{
    var redObj=document.getElementById("red");
    redObj.attachEvent("onclick",clickHandle);
    redObj.attachEvent("onmouseout",mouseoutHandle("mouseout"));
}
function clickHandle()
{
    try{
        alert(arguments[0].type);
    }catch(e){
        alert(e.name+":"+e.message);
    }
}
function mouseoutHandle(type)
{
    return function(){
        alert(type);
        alert(arguments.length);    
    };
}
</script>
</head>
<body>
  <div id="red" style="width:50px;height:50px;background-color:red"></div>
  <div id="black" style="width:50px;height:50px;background-color:black" onclick="clickHandle(event)"></div>
</body>
</html>

#6


本帖最后由 cj205 于 2011-01-12 17:45:06 编辑
三种绑定方式
你看下不同的结果

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
function clickHandle(e) {
alert(e.type);
}
window.onload = function() {
document.getElementById("red").onclick = function(event) {
alert(event);
}
document.getElementById("red").attachEvent("onmouseover",function(e) {alert(e.type);});
};
</script>
</head>
<body>
  <div id="red" style="width:50px;height:50px;background-color:red"></div>
  <div id="black" style="width:50px;height:50px;background-color:black" onclick="clickHandle(event)"></div>
</body>
</html>

#1


该回复于2011-01-12 14:25:50被版主删除

#2


document.getElementById('sss').attachEvent('onclick',function(e){
alert(e.type);
})
测试的是,这个在IE5.5下都可以弹出event.type。
也就是说attachEvent可以传入Event对象。
但是this指向的是window。

htmlElement.onclick = function(e){}IE就不能传入Event对象了,而this指向的是htmlElement。

#3


引用 2 楼 crazywa 的回复:
document.getElementById('sss').attachEvent('onclick',function(e){
alert(e.type);
})
测试的是,这个在IE5.5下都可以弹出event.type。
也就是说attachEvent可以传入Event对象。
但是this指向的是window。

htmlElement.onclick = functio……

就像你说的,事实就是:attachEvent可以传入Event对象。我贴的例子也说明了这个,但是我记得attachEvent的事件函数不该可以传Event对象的啊?
下面是我做的小测试。

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
window.onload=function()
{
var redObj=document.getElementById("red");
redObj.attachEvent("onclick",clickHandle);
redObj.attachEvent("onmouseout",mouseoutHandle("mouseout"));
}
function clickHandle()
{
try{
alert(arguments[0].type);
}catch(e){
alert(e.name+":"+e.message);
}
}
function mouseoutHandle(type)
{
return function(){
alert(type);
alert(arguments.length);
};
}
</script>
</head>
<body>
  <div id="red" style="width:50px;height:50px;background-color:red"></div>
  <div id="black" style="width:50px;height:50px;background-color:black" onclick="clickHandle()"></div>
</body>
</html>

欢迎讨论啊,疑惑着呢,还有关于this绑定,散分。

#4


该回复于2011-01-12 17:36:35被版主删除

#5


行,那我把你的demo修改下 你再看看

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
window.onload=function()
{
    var redObj=document.getElementById("red");
    redObj.attachEvent("onclick",clickHandle);
    redObj.attachEvent("onmouseout",mouseoutHandle("mouseout"));
}
function clickHandle()
{
    try{
        alert(arguments[0].type);
    }catch(e){
        alert(e.name+":"+e.message);
    }
}
function mouseoutHandle(type)
{
    return function(){
        alert(type);
        alert(arguments.length);    
    };
}
</script>
</head>
<body>
  <div id="red" style="width:50px;height:50px;background-color:red"></div>
  <div id="black" style="width:50px;height:50px;background-color:black" onclick="clickHandle(event)"></div>
</body>
</html>

#6


本帖最后由 cj205 于 2011-01-12 17:45:06 编辑
三种绑定方式
你看下不同的结果

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Untitled 1</title>
<script type="text/javascript">
function clickHandle(e) {
alert(e.type);
}
window.onload = function() {
document.getElementById("red").onclick = function(event) {
alert(event);
}
document.getElementById("red").attachEvent("onmouseover",function(e) {alert(e.type);});
};
</script>
</head>
<body>
  <div id="red" style="width:50px;height:50px;background-color:red"></div>
  <div id="black" style="width:50px;height:50px;background-color:black" onclick="clickHandle(event)"></div>
</body>
</html>