window.attachEvent 实现 window.load多个函数

本文介绍了在不同浏览器中实现事件监听的兼容性方案,包括使用attachEvent和addEventListener方法,并提供了一个实用函数来简化这一过程。
以前写 JavaScript 脚本时,事件都是采用
object.event = handler;
的方式初始化。这种方式对于 Internet Explorer、Mozilla/Firefox 和 Opera 来说很通用。但是有一个问题就是,这种方式只能一个事件对应一个事件处理过程。如果希望一个事件可以依次执行多个处理过程就不好用了。

但是 Internet Explorer 从 5.0 开始提供了一个 attachEvent 方法,使用这个方法,就可以给一个事件指派多个处理过程了。attachEvent 对于目前的 Opera 也适用。但是问题是 Mozilla/Firefox 并不支持这个方法。但是它支持另一个 addEventListener 方法,这个方法跟 attachEvent 差不多,也是用来给一个事件指派多个处理过程的。但是它们指派的事件有些区别,在 attachEvent 方法中,事件是以 “on” 开头的,而在 addEventListener 中,事件没有开头的 “on”,另外 addEventListener 还有第三个参数,一般这个参数指定为 false 就可以了。


因此要想在你的程序中给一个事件指派多个处理过程的话,只要首先判断一下浏览器,然后根据不同的浏览器,选择使用 attachEvent 还是 addEventListener 就可以了。实例如下:

Java代码
if (document.all) {    
window.attachEvent('onload', handler1);
window.attachEvent('onload', handler2);
}
else {
window.addEventListener('load', handler1, false);
window.addEventListener('load', handler2, false);
}

if (document.all) {
window.attachEvent('onload', handler1);
window.attachEvent('onload', handler2);
}
else {
window.addEventListener('load', handler1, false);
window.addEventListener('load', handler2, false);
}



注意:attachEvent 所指派的多个过程的执行顺序是随机的,所以这几个过程之间不要有顺序依赖。另外 attachEvent 和 addEventListener 不仅仅适用于 window 对象,其他的一些对象也支持该方法。

另外为了方便我也写了个function sunet_addEvent(obj, evType, fn),如下:


Java代码
function sunet_addEvent(obj, evType, fn)    
{
if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
}else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
}else{
return false;
}
}

function sunet_addEvent(obj, evType, fn)
{
if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
}else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
}else{
return false;
}
}


// 调用例子: Java代码
sunet_addEvent(window,"locad",init);   

sunet_addEvent(window,"locad",init);



JavaScript中的5种事件使用方式解说(转)
为组件提供事件处理入口,可以极大的提高组件的封闭性,同时又能让组件很好的和外界通信。并且这也是我们已经习惯使用的一种开发模式,.NET、DHTML等都提供了一套完整的事件处理模型。下面是关于使用DHTML中事件的一个总结。

DHTML提供了3种事件的使用方式,它们分别是:

1、Inline HTML: <ELEMENT onXXX='handler'></ELEMENT>
这是最简单最常用的事件绑定方式,不过这里onXXX的值为handler是不太确切的说法。其实这个handler的位置可以放置任何合法的JavaScript语句,因为IE在生成DHMTL树时会为当前Element构建一个'匿名'成员方法,onXXX指向这个方法的handler。比如我们写下
<element id='elmt' onXXX='var abc =0; for ( var i=0 ; i < 100 ; i++ ) abc+=i;'></element>
实际上在DHMTL树种存在如下代码结构:
function anonymous() 
{
var abc =0; for ( var i=0 ; i < 100 ; i++ ) abc+=i;
}

此时anonymous方法中的this就是elmt对象。

2、Event property: object.onXXX = handler
这个使用方法是把函数名(handler)赋予element预定义的事件属性上(onXXX)。这里需要注意两个问题:
一是,我们在使用object.onXXX = handler是需要保证object已经在页面中生成。比如我们为document.body赋予事件处理函数,我们必须保证document.body已经存在,就是说我们不能在<body>之前在的全局语句中使用document.body;
二是,handler必须是函数名,和使用方法1中的handler可以是任何JavaScript语句不同!我们最容易出错的使用是,当我们习惯了在inline html中使用
<element id='elmt' onXXX = 'return false'></element>
后,如果这样使用
elmt.onXXX='return false;'
。那么就歇菜了,不会有任何执行效果,当然IE也不报错。正确的使用是:

elmt.onXXX = function() { return false; } 


3、Named Script: <SCRIPT FOR = object EVENT = onclick>
IE独家支持,没有怎么使用过,不觉得有什么特别的地方哈。如果您知道它的妙处愿闻其详。

DOM提供了两种事件处理使用,它们分别是:

1、attachEvent method:
使用方法:bSuccess = object.attachEvent(sEvent, fpNotify)。解释就抄msdn了
Parameters
sEvent Required. String that specifies any of the standard DHTML Events.
fpNotify Required. Pointer that specifies the function to call when sEvent fires.
Return Value
Boolean. Returns one of the following possible values: true The function was bound successfully to the event.
false The function was not bound to the event.
DOM提供的这个事件附加方式实际上是一个集合操作,我们可以多次的向同一个事件签名上attach多个事件处理函数,比如:

window.attachEvent('onload', handler1);
window.attachEvent('onload', handler2);
window.attachEvent('onload', handler3);
window.attachEvent('onload', handlerN);

将会执行这个N个handler,但是不保证执行顺序。这里有个例外,attachEvent在document.body上attach事件'onload'没有效果,但是attch window对象的'onload'是正确的。根据页面初始化顺序来看,及document.body.attachEvent('onload', handler)返回true来看,这因该是IE的一个bug。

注意DHTML的Event Property方式和DOM的attachEvent方式的区别:

Event Property方式,当触发事件时,事件处理函数是一个无参数函数,我们只能通过event这个window的属性来读取和事件相关的信息。attachEvent方式,当事件处理函数被触发时,该函数的第一个参数arguments[0],默认是该窗口上的event。
### 问题分析 在使用 `window.addEventListener` 时遇到返回 `undefined` 的问题,通常与代码执行环境的设置或浏览器兼容性相关。`window.addEventListener` 是标准的 DOM API,用于监听指定事件(如 `click`、`load` 等),其基本语法如下: ```javascript window.addEventListener('event', function, options); ``` 该方法本身返回 `undefined`,这是预期行为,并非错误[^1]。然而,开发者在调试过程中可能误以为该返回值应为某个对象或函数,从而导致困惑。更常见的情况是,代码逻辑中尝试访问某个未定义的变量或未正确绑定函数上下文,从而引发 `undefined` 错误。 ### 常见问题与修复方法 #### 1. **确保代码在 DOM 加载完成后执行** 如果代码在 DOM 完全加载之前运行,可能会导致 `window` 或相关元素未准备好,从而引发错误。可通过以下方式确保代码在 DOM 加载后执行: ```html <script> window.addEventListener('DOMContentLoaded', function () { // 在此处编写监听器逻辑 window.addEventListener('resize', handleResize); }); function handleResize() { console.log('Window resized'); } </script> ``` #### 2. **检查浏览器兼容性** 虽然现代浏览器普遍支持 `addEventListener`,但在某些旧版浏览器(如 IE8 及以下)中并不兼容。可通过特性检测进行兼容性处理: ```javascript if (window.addEventListener) { window.addEventListener('scroll', handleScroll); } else if (window.attachEvent) { window.attachEvent('onscroll', handleScroll); // 适用于旧版 IE } ``` #### 3. **确保函数定义正确** 如果传递给 `addEventListener` 的函数未正确定义或拼写错误,可能导致运行时错误。例如: ```javascript // 错误示例 window.addEventListener('load', handelLoad); // 函数名拼写错误 // 正确示例 function handleLoad() { console.log('Page loaded'); } window.addEventListener('load', handleLoad); ``` #### 4. **避免作用域问题** 使用匿名函数时,需确保其上下文不会因异步执行而丢失。可通过 `bind` 明确绑定 `this`: ```javascript const obj = { value: 42, init() { window.addEventListener('click', function () { console.log(this.value); // this 指向 window }); window.addEventListener('click', function () { console.log(this.value); // this 指向 obj }.bind(this)); } }; obj.init(); ``` #### 5. **使用模块化开发工具确保环境正确** 在现代前端开发中,使用构建工具(如 Webpack、Vite)和模块化语法(如 `import`/`export`)时,需确保入口文件正确加载并执行。例如: ```javascript // main.js import { setupListeners } from './listeners'; setupListeners(); ``` ```javascript // listeners.js export function setupListeners() { window.addEventListener('load', () => { console.log('Listeners set up'); }); } ``` ### 开发环境建议 - **使用现代浏览器进行调试**(如 Chrome、Firefox),并启用开发者工具查看控制台输出。 - **启用 ESLint 或 TypeScript**,以捕获潜在的变量未定义或拼写错误。 - **避免全局污染**,使用 IIFE(立即执行函数表达式)或模块化结构封装代码。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值