js使用函数绑定技术改变事件处理程序的作用域

 更新时间:2011年12月26日 23:46:20   作者:  
在html页面里面为某个元素的事件指定处理程序有很多种方式
第一种,也是 最常见的,就是直接在html标签里面通过指定事件处理程序同名的HTML属性来注册事件,代码如下:
复制代码 代码如下:

function eventHandler() {
alert("当前作用域是 input 元素本身");
}
<input type="button" value="单击我" onclick="eventHandler(this)"/>

第二种方式就是将一个函数赋值给一个事件处理程序属性。这种方式首先的获取到这个元素对象,一般代码如下:
复制代码 代码如下:

<input id="myEventHandlerScope" type="button" value="单击我"/>
<script type="text/javascript">
function eventHandler() {
alert("当前作用域是 input 元素本身");
}
var mybtn = document.getElementById("myEventHandlerScope");
mybtn.onclick = eventHandler;
</script>

第三种方式,就是理由DOM2级别的事件处理方法 addEventListener和removeEventListener,针对ie浏览器对应的方法是attachEvent 和 detachEvent。注册事件的代码如下:
复制代码 代码如下:

<input id="myEventHandlerScope" type="button" value="单击我"/>
<script type="text/javascript">
//定义一个注册事件的方法
function addHandler(obj, type, handler) {
if (obj.addEventListener) {
obj.addEventListener(type, handler, false);
} else if (obj.attachEvent) {
obj.attachEvent("on" + type, handler);
} else {
obj["on" + type] = handler;
}
}
function eventHandler() {
alert("当前作用域是 input 元素本身");
}
var mybtn = document.getElementById("myEventHandlerScope");
addHandler(mybtn,'click',eventHandler);//为对象注册事件
</script>

input对象的Click事件执行环境截图
通过以上3种方式为input元素注册一个 click 事件处理程序都有一个缺点就是这个处理程序的作用域(this)始终处于input对象。在面向对象编程的时候,就需要明确的指定this在特定的作用域下面。 为了改变this的作用域,就得用到js的一种绑定函数技术。
所谓“绑定函数”就是要创建一个函数,可以在特定环境中以指定参数调用另一个函数,他能很好的与事件处理程序一起使用,以便在将函数作为变量传递的同时保持函数的作用域(也是this的执行环境)。绑定函数的定义形式如下代码:

复制代码 代码如下:

function bind(fn,scope) {
return fn.apply(scope||this,arguments);
}

这个绑定函数接受两个参数,第一个是需要执行的函数,第二个是特定的执行环境,并返回一个在给定作用域中调用给定函数,并将所有参数一同传递过去。利用绑定函数技术和DOM2级的事件处理程序就能很好的为元素注册一个在特定作用域下执行的事件处理函数。具体的处理方式如下:
首先修改先前定义的注册事件的方法如下代码:
复制代码 代码如下:

function addHandler(obj, type, handler, scope) {
function fn(event) {
var evt = event ? event : window.event;
evt.target = event.target || event.srcElement;
return handler.apply(scope || this,arguments);
}
obj.eventHash = obj.eventHash || {};//这里为需要注册事件处理程序的对象定义一个保存事件的hash对象,并把事件处理程序和作用域保存在该事件类型的队列里面
(obj.eventHash [type] = obj.eventHash [type] || []).push({ "name": type, "handler": handler, "fn": fn, "scope": scope });
if (obj.addEventListener) {
obj.addEventListener(type, fn, false);
} else if (obj.attachEvent) {
obj.attachEvent("on" + type, fn);
} else {
obj["on" + type] = fn;
}
}

使用修改后的注册事件方法就可以使元素的事件处理程序在指定的环境里面执行了。
复制代码 代码如下:

<input id="myEventHandlerScope" type="button" value="单击我"/>
<script type="text/javascript">
function eventHandler() {
this;
alert("当前作用域是 window 元素本身");
}
var mybtn = document.getElementById("myEventHandlerScope");
addHandler(mybtn, 'click', eventHandler,window);
</script>

执行上面这段代码,处理程序eventHandler的this作用域就处在了window对象下面。

this在window对象下的执行环境截图

在前面介绍的通过绑定函数注册事件是为元素对象创建了一个事件的hash对象用来保存事件处理程序,这个hash对象在元素移除事件处理程序的时候起到了非常总要左右,根据他就能准确的移除对应的事件处理程序。移除事件处理程序的代码如下:
复制代码 代码如下:

function removeHandler (obj, type, handler, scope) {
obj.eventHash = obj.eventHash || {};
var evtList = obj.eventHash [type] || [], len = evtList.length;
if (len > 0) {
for (; len--; ) {
var curEvtObj = evtList[len];
if (curEvtObj.name == type && curEvtObj.handler === handler && curEvtObj.scope === scope) {
if (obj.removeEventListener) {
obj.removeEventListener(type, curEvtObj.fn, false);
} else if (obj.detachEvent) {
obj.detachEvent("on" + type, curEvtObj.fn);
} else {
obj["on" + type] = null;
}
evtList.splice(len, 1);
break;
}
}
}
}

到这里就介绍完了使用函数绑定技术注册特定执行环境的事件处理程序。同样,利用函数绑定还能使回调函数在给定的执行环境里面执行。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

相关文章

  • javascript canvas时钟模拟器

    javascript canvas时钟模拟器

    这篇文章主要为大家详细介绍了javascript canvas时钟模拟器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • js html5获取input焦点的输入框并赋值实例

    js html5获取input焦点的输入框并赋值实例

    这篇文章主要为大家介绍了js html5获取input焦点的输入框并赋值实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Bootstrap图片轮播效果详解

    Bootstrap图片轮播效果详解

    这篇文章主要为大家详细介绍了Bootstrap图片轮播效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • JavaScript通过select动态更换图片的方法

    JavaScript通过select动态更换图片的方法

    这篇文章主要介绍了JavaScript通过select动态更换图片的方法,涉及javascript动态操作图片src的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • mint-ui的search组件在键盘显示搜索按钮的实现方法

    mint-ui的search组件在键盘显示搜索按钮的实现方法

    这篇文章主要介绍了mint-ui的search组件在键盘显示搜索按钮的实现方法,需要的朋友可以参考下
    2017-10-10
  • JavaScript模块化原理深入分析

    JavaScript模块化原理深入分析

    JavaScript中的模块化是指将每个js文件会被认为单独一个的模块。模块之间是互相不可见的。如果一个模块需要使用另一个模块,那么需要通过指定语法来引入要使用的模块,而且只能使用引入模块所暴露的内容
    2022-11-11
  • Javascript removeChild()删除节点及删除子节点的方法

    Javascript removeChild()删除节点及删除子节点的方法

    这篇文章主要介绍了Javascript removeChild()删除节点及删除子节点的方法的相关资料,需要的朋友可以参考下
    2015-12-12
  • uni-app使用Vite.config.js配置文件的超详细教程

    uni-app使用Vite.config.js配置文件的超详细教程

    这篇文章主要给大家介绍了关于uni-app使用Vite.config.js配置文件的超详细教程,在uniapp开发中,vue.config.js是配置webpack的关键文件之一,也可以说是uniapp项目自定义配置的中心,需要的朋友可以参考下
    2023-12-12
  • Postman的FormData传参的使用示例详解

    Postman的FormData传参的使用示例详解

    今年上半年因为做毕设的原因,有自己接触到后端,也是用过了postman去测试接口,看到了postman那边的参数形式,一直对这个formData有想法,今天通过本文给大家介绍Postman的FormData传参的使用,感兴趣的朋友一起看看吧
    2023-10-10
  • 热点新闻滚动特效的js代码

    热点新闻滚动特效的js代码

    我们在很多大型门户网站都会有看到有些一热点新闻都会一直向上滚动,下面我就来给大家推荐一款Javascript中热点新闻滚动特效代码,有需要了解的朋友可以参考一下
    2013-08-08

最新评论