一段js,求解释
(function(){
if (!Function.prototype.bind) {
alert(1);
Function.prototype.bind = function(obj){
alert(2);
var owner = this, args = Array.prototype.slice.call(arguments),
callobj = Array.prototype.shift.call(args);
return function(e){
alert(1);
e = e || top.window.event || window.event;
owner.apply(callobj, args.concat([e]));
};
};
}
})();
callobj = Array.prototype.shift.call(args); //取第一参数
return function(e){
alert(1);
//判断用e取从左到右有值的第一个
e = e
[解决办法]
top.window.event
[解决办法]
window.event;
//函数的当前对象为callobj也就是第一个参数,并传后面的参数
owner.apply(callobj, args.concat([e]));
};
};
}
})();
[解决办法]
(1)js函数具有一些常规的属性和方法,比如length属性(表示函数参数的个数)和call,apply方法(转换函数的this对象),这些属性方法都来自js函数的原型上,即Function.prototype。
简单来讲,这段代码的意思就是:
检查函数原型中是否存在名叫bind的方法,如果存在什么都不执行,如果不存在就给原型加上一个bind方法。
调用bind的结果是返回一个新函数,新函数中将‘调用bind的函数的this’指定为‘调用时传到bind中的参数的第一个参数’,将‘调用bind的函数的参数’指定为‘调用时传到bind中的所有参数+e(事件对象)’。
(2)可以自己做个小例子(前提是要保证if(...)可以顺利执行,可以找一个版本较低的浏览器),看一下:
function foo(){
alert(this.length)
};
//调用bind;
foo.bind('b','c');
//因为bind方法返回一个新函数(可以通过consloe.log(foo.bind('b','c')))在控制台里检测一下,
//所以可以如下所示执行新函数。
//返回的新函数执行时,实际上是在执行:foo.apply('b',['b','c',e]),
//此时foo内部的this指向了'b'所以最后弹出的是1(字符串b的length)。
//因为foo在定义时并没有指定要传参,所以在这里['b','c',e]就没有什么意义了。
foo.bind('b','c')();//弹出:1
<input type="button" name="NotBind" id= "notBind" value="Not bind">
<input type="button" name="Bind" id= "bind" value="Bind">
<SCRIPT type="text/javascript">
<!--
(function(){
if (!Function.prototype.bind) {
alert(1);
Function.prototype.bind = function(obj){
alert(2);
var owner = this, args = Array.prototype.slice.call(arguments),
callobj = Array.prototype.shift.call(args);
return function(e){
alert(1);
e = e
[解决办法]
top.window.event
[解决办法]
window.event;
owner.apply(callobj, args.concat([e]));
};
};
}
})();
var ob = {
name:"'This' is the object ob, not the button"
}
var find= function (name) {
return document.getElementById(name);
}
find("notBind").onclick= function () {
alert(this.name);
}
find("bind").onclick= (function () {
alert(this.name);
}).bind(ob);
//-->
</SCRIPT>
//修改之前的原代码:
find("bind").onclick= (function () {
alert(this.name);
}).bind(ob);
//修改之后:传入了参数e,并加了一行alert(e.clientX)
find("bind").onclick= (function (e) {
alert(this.name);
//下面为新代码,client是事件对象的属性,
//意思是事件发生时鼠标相对于屏幕的横坐标的值,在这里就是单击按钮时鼠标的横坐标
alert(e.clientX);
}).bind(ob);
return function(){//去掉了参数e
alert(1);
e = e
[解决办法]
top.window.event
------解决方案--------------------
window.event;
owner.apply(callobj, args.concat([e]));
};
//给按钮绑定的事件函数并不是
//find("bind").onclick=
(function (e) {
alert(this.name);
alert(e.clientX)
}).bind(ob)
//而是
function(e){
e = e
[解决办法]
top.window.event
[解决办法]
window.event;
(function (e) {
alert(this.name);
alert(e.clientX)
}).apply(ob, [e]);
}
//所以按钮的单击事件对象e是存在于这个函数中的而不是onclick后面的函数,如果想进行关于事件对象e的操作只能在bind返回的新函数中进行。但是bind是为所有函数定义的公有方法,不可能为了某个按钮的操作在里面进行对e的操作,所以把e(代码中的(obj,[e]))传给了调用bind方法的函数(也就是onclick后的函数),这样就可以在自己定义的函数里对e进行任意操作了。