javascript - addLoadEvents 这个函数的原理
PHP中文网
PHP中文网 2017-04-11 13:02:35
[JavaScript讨论组]

JS新手请问大家addLoadEvents的原理是什么?

    

这个是打印结果:是正常的而且令人满意的.

这个是window.onload默认的绑定事件.
这个是追加fn1
这个是追加fn2
这个是追加fn3

但是从代码运行来看打印的结果应该是这样的呀:

这个是window.onload默认的绑定事件.
这个是追加fn1
这个是window.onload默认的绑定事件.
这个是追加fn2
这个是window.onload默认的绑定事件.
这个是追加fn3

为什么很巧妙的规避默认window.onload事件函数的重复执行了呢? 麻烦大家,谢谢!

PHP中文网
PHP中文网

认证高级PHP讲师

全部回复(3)
黄舟

其实也不巧妙吧,刚才看得有点懵逼。

var i=0;

        window.onload = function(){
                    console.log(i);
            console.log("这个是window.onload默认的绑定事件.")
        }

        function addLoadEvents(fn){
                    i++;
            var oldEvents = window.onload;
            if(typeof oldEvents != 'function'){
                window.onload = fn;
            }else{
                window.onload = function(){
                    oldEvents();
                    fn();
                }
            }
        }

        function fn1(){
            console.log("这个是追加fn1");
        }        
        function fn2(){
            console.log("这个是追加fn2");
        }        
        function fn3(){
            console.log("这个是追加fn3");
        }

        addLoadEvents(fn1);
        addLoadEvents(fn2);
        addLoadEvents(fn3);

试着用一个i来记录,才意识到,这个onload就执行了一次,因为addLoadEvents把onload回调改写了:先执行前一个onload回调,然后再执行新回调。
所以代码一走下来,就是 默认的回调+fn1的执行+fn2+fn3
所以可以看到执行结果是

3
这个是window.onload默认的绑定事件.
这个是追加fn1
这个是追加fn2
这个是追加fn3
大家讲道理

因为在运行addLoadEvents(fn2)的时候取到的oldEvents的结果里面就包含了fn1()。依此类推,自然就是你说的那个结果。

最后,这个叫桥接模式。

-------------------------------------------------------补充-----------------------------------------------------

要实现你提到的那种效果(虽然你可能认为是错误的效果,但是我还是实现一下吧),如下:

var events = [];

function on(obj, type, handler) {
    // 检查obj和type....
    // 总之有这里非常多的验证工作先和细节先省略了
    events.push({
        obj: obj,
        type: type,
        handlerByOn: handler // 通过on的方式添加的handler
    });

    obj.addEventListener(type, function() {
        events.forEach(function(e) { // 这里要检验events中与obj相符,也省略了
            e.handlers.forEach(function(hd) {
                hd();
            });
        });
    });
}

function addLoadEvents(obj, type, handler){
    var oldEvent = events.find(function(e) {return e.obj === obj && e.type === type;});

    var newHandler = function() {
        oldEvent.handlerByOn();
        handler();
    };

    oldEvent && oldEvent.handlers ? oldEvent.handlers.push(newHandler) : oldEvent.handlers = [newHandler];
}

function fn1(){
    console.log("这个是追加fn1");
}
function fn2(){
    console.log("这个是追加fn2");
}
function fn3(){
    console.log("这个是追加fn3");
}

on(window, 'load', function() {
    console.log("这个是window.onload默认的绑定事件.")
});

addLoadEvents(window, 'load', fn1);
addLoadEvents(window, 'load', fn2);
addLoadEvents(window, 'load', fn3);

运行结果如图:

迷茫

个人理解这里跟window.onload执行机制有关,onload会等到页面dom,图片,音视频,js等都加载解析完成才会执行,因此三个addLoadEvents函数都是在往window.onload里添加函数,最后js解析完成开始执行window.onload

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号