javascript的事件触发和接收源码

define(function(require,exports,module){

    var Events=function(){
        var array = [];
        var push = array.push;
        var slice = array.slice;
        var splice = array.splice;
        var Events  = {

            // Bind an event to a `callback` function. Passing `"all"` will bind
            // the callback to all events fired.
            on: function(name, callback, context) {
                if (!eventsApi(this, ‘on‘, name, [callback, context]) || !callback) return this;
                this._events || (this._events = {});
                var events = this._events[name] || (this._events[name] = []);
                events.push({callback: callback, context: context, ctx: context || this});
                return this;
            },

            // Bind an event to only be triggered a single time. After the first time
            // the callback is invoked, it will be removed.
            once: function(name, callback, context) {
                if (!eventsApi(this, ‘once‘, name, [callback, context]) || !callback) return this;
                var self = this;
                var once = _.once(function() {
                    self.off(name, once);
                    callback.apply(this, arguments);
                });
                once._callback = callback;
                return this.on(name, once, context);
            },

            // Remove one or many callbacks. If `context` is null, removes all
            // callbacks with that function. If `callback` is null, removes all
            // callbacks for the event. If `name` is null, removes all bound
            // callbacks for all events.
            off: function(name, callback, context) {
                var retain, ev, events, names, i, l, j, k;
                if (!this._events || !eventsApi(this, ‘off‘, name, [callback, context])) return this;
                if (!name && !callback && !context) {
                    this._events = {};
                    return this;
                }

                names = name ? [name] : _.keys(this._events);
                for (i = 0, l = names.length; i < l; i++) {
                    name = names[i];
                    if (events = this._events[name]) {
                        this._events[name] = retain = [];
                        if (callback || context) {
                            for (j = 0, k = events.length; j < k; j++) {
                                ev = events[j];
                                if ((callback && callback !== ev.callback && callback !== ev.callback._callback) ||
                                    (context && context !== ev.context)) {
                                    retain.push(ev);
                                }
                            }
                        }
                        if (!retain.length) delete this._events[name];
                    }
                }

                return this;
            },

            // Trigger one or many events, firing all bound callbacks. Callbacks are
            // passed the same arguments as `trigger` is, apart from the event name
            // (unless you‘re listening on `"all"`, which will cause your callback to
            // receive the true name of the event as the first argument).
            trigger: function(name) {
                if (!this._events) return this;
                var args = slice.call(arguments, 1);
                if (!eventsApi(this, ‘trigger‘, name, args)) return this;
                var events = this._events[name];
                var allEvents = this._events.all;
                if (events) triggerEvents(events, args);
                if (allEvents) triggerEvents(allEvents, arguments);
                return this;
            },

            // Tell this object to stop listening to either specific events ... or
            // to every object it‘s currently listening to.
            stopListening: function(obj, name, callback) {
                var listeners = this._listeners;
                if (!listeners) return this;
                var deleteListener = !name && !callback;
                if (typeof name === ‘object‘) callback = this;
                if (obj) (listeners = {})[obj._listenerId] = obj;
                for (var id in listeners) {
                    listeners[id].off(name, callback, this);
                    if (deleteListener) delete this._listeners[id];
                }
                return this;
            }

        };

        // Regular expression used to split event strings.
        var eventSplitter = /\s+/;

        // Implement fancy features of the Events API such as multiple event
        // names `"change blur"` and jQuery-style event maps `{change: action}`
        // in terms of the existing API.
        var eventsApi = function(obj, action, name, rest) {
            if (!name) return true;

            // Handle event maps.
            if (typeof name === ‘object‘) {
                for (var key in name) {
                    obj[action].apply(obj, [key, name[key]].concat(rest));
                }
                return false;
            }

            // Handle space separated event names.
            if (eventSplitter.test(name)) {
                var names = name.split(eventSplitter);
                for (var i = 0, l = names.length; i < l; i++) {
                    obj[action].apply(obj, [names[i]].concat(rest));
                }
                return false;
            }

            return true;
        };

        // A difficult-to-believe, but optimized internal dispatch function for
        // triggering events. Tries to keep the usual cases speedy (most internal
        // Backbone events have 3 arguments).
        var triggerEvents = function(events, args) {
            var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
            switch (args.length) {
                case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
                case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
                case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
                case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
                default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
            }
        };

        // Aliases for backwards compatibility.
        Events.bind   = Events.on;
        Events.unbind = Events.off;
        return Events;
    }()

module.exports=Events

})
时间: 2024-10-10 19:44:36

javascript的事件触发和接收源码的相关文章

QWidget 键盘事件 焦点(QApplication源码)

在Qt中,键盘事件和QWidget的focus密不可分:一般来说,一个拥有焦点(focus)的QWidget或者grabKeyboard()的QWidget才可以接受键盘事件. 键盘事件派发给谁? 如何确定谁来接收键盘事件,不妨看一点点QApplication的源码: X11下 QETWidget *keywidget=0; bool grabbed=false; if (event->type==XKeyPress || event->type==XKeyRelease) { keywidg

android判断双击事件(参考android源码,判断时间间隔和范围)

对于android的双击事件的判断,官方是已经给出解决办法的,主要是使用下面几个类或者接口:GestureDetector,OnGestureListener,OnDoubleTapListener,GestureDetector.SimpleOnGestureListener 对于它们的介绍以及用法很多了,就不说明了,大家可以参考下面的博客: http://blog.sina.com.cn/s/blog_77c6324101017hs8.html 需要特殊说明的是OnDoubleTapList

javascript arguments对象研究--针对jquery源码研究再研究

外部插件: $.fn.tinytip = function(text, customOptions) { debugger; if (text && typeof text === 'object'){ customOptions = text; text = customOptions.tooltip; } var options = $.extend({}, tooltip_options, customOptions); options.tooltip = text; if (typ

【JavaScript】$.extend使用心得及源码研究

最近写多了js的面向对象编程,用$.extend写继承写得很顺手.但是在使用过程中发现有几个问题. 1.深拷贝 $.extend默认是浅拷贝,这意味着在继承复杂对象时,对象中内嵌的对象无法被拷贝到. 因此如果要深拷贝,则需要将第一个参数设置为true. 如: var a = { a:1 }; var b = { b:{c:1} }; $.extend(a,b); a = { a:1,b:{c:1} }; 2.对象覆盖 在进行面向对象编程时,有这么一种情况. 比如有一个公共对象,某个类在实例化的时

javaScript数组知识梳理与排列三源码出售

数组的概念:排列三源码出售(企 娥:217 1793 408) 数组中的每个元素的类型可以是不同的,可以是数值型,字符串型和布尔型,甚至也可以是一个数组 1.使用构造函数Array定义数组, 2.直接定义数组 delete:删除数组元素,数组元素的个数不会变,改变的是元素的值,变为undefined length:返回数组的长度,数组的长度有其最大下表决定 protoytpe:可以数组添加自定义的属性和方法 数组对象的方法: concat():链接两个或者更过的数组,并返回其结果 push():

backbone event 事件订阅 和发布 源码小读

nodejs有eventEmitter 类,想到backbone  有个event模块 可以对对象做事件绑定和触发,是backbone的核心模块. backbone event模块 on 添加自定义事件 off 删除自定义事件 trigger 派发自定义事件 once 添加只执行一次的自定义事件 (内部依赖于_.once) listenTo 添加一个观察对象 listenToOnce 添加一个仅执行一次的观察对象 stopListening 删除添加的观察对象 -----------------

事件分发机制之 源码解析

事件的下发:dispatchTouchEvent ViewGroup相关事件有三个:onInterceptTouchEvent.dispatchTouchEvent.onTouchEvent View相关事件有两个:dispatchTouchEvent.onTouchEvent 简单来说就是:当一个Touch事件到达根节点时,它会依次[下发],下发的过程是调用子View的dispatchTouchEvent方法实现的. 详细来说就是:ViewGroup遍历它包含着的[子View],如果Touch

storm事件管理器EventManager源码分析-event.clj

storm事件管理器定义在event.clj中,主要功能就是通过独立线程执行"事件处理函数".我们可以将"事件处理函数"添加到EventManager的阻塞队列中,EventManager的事件处理线程不断地从阻塞队列中获取"事件处理函数"并执行. EventManager协议 协议就是一组函数定义的集合,协议中函数的第一个参数必须为实现该协议的实例本身,类似于java中实例方法的第一个参数为this:协议类似于java中的接口. (defpro

&lt;JavaScript语言精粹&gt;JSON解析器源码阅读

1 // 这是一个用JavaScript编写JSON解析器的实现方案: 2 var jsonParser = (function() { 3 // 这是一个能把JSON文本解析成JavaScript数据结构的函数. 4 // 它是一个简单的递归降序解析器. 5 // 我们在另一个函数中定义此函数,以避免创建全局变量. 6 7 var at, // 当前字符索引 8 ch, // 当前字符 9 escapee = { 10 '"': '"', 11 "\\": &qu