/**
 * @file  Event Emitter
 * @author  Firede(firede@firede.us)
 */

(function () {

    /**
     * Emitter
     *
     * @exports Emitter
     * @constructor
     */
    function Emitter() {}

    /**
     * Emitter的prototype（为了便于访问）
     *
     * @inner
     */
    var proto = Emitter.prototype;

    /**
     * 获取事件列表
     * 若还没有任何事件则初始化列表
     *
     * @private
     * @return {Object}
     */
    proto._getEvents = function () {
        if (!this._events) {
            this._events = {};
        }

        return this._events;
    };

    /**
     * 获取最大监听器个数
     * 若尚未设置，则初始化最大个数为10
     *
     * @private
     * @return {number}
     */
    proto._getMaxListeners = function () {
        if (isNaN(this.maxListeners)) {
            this.maxListeners = 10;
        }

        return this.maxListeners;
    };

    /**
     * 挂载事件
     *
     * @public
     * @param {string} event 事件名
     * @param {Function} listener 监听器
     * @return {Emitter}
     */
    proto.on = function (event, listener) {
        var events = this._getEvents();
        var maxListeners = this._getMaxListeners();

        events[event] = events[event] || [];

        var currentListeners = events[event].length;
        if (currentListeners >= maxListeners && maxListeners !== 0) {
            throw new RangeError(
                'Warning: possible Emitter memory leak detected. '
                + currentListeners
                + ' listeners added.'
           );
        }

        events[event].push(listener);

        return this;
    };

    /**
     * 挂载只执行一次的事件
     *
     * @public
     * @param {string} event 事件名
     * @param {Function} listener 监听器
     * @return {Emitter}
     */
    proto.once = function (event, listener) {
        var me = this;

        function on() {
            me.off(event, on);
            listener.apply(this, arguments);
        }
        // 挂到on上以方便删除
        on.listener = listener;

        this.on(event, on);

        return this;
    };

    /**
     * 注销事件与监听器
     * 任何参数都`不传`将注销当前实例的所有事件
     * 只传入`event`将注销该事件下挂载的所有监听器
     * 传入`event`与`listener`将只注销该监听器
     *
     * @public
     * @param {string=} event 事件名
     * @param {Function=} listener 监听器
     * @return {Emitter}
     */
    proto.off = function (event, listener) {
        var events = this._getEvents();

        // 移除所有事件
        if (0 === arguments.length) {
            this._events = {};
            return this;
        }

        var listeners = events[event];
        if (!listeners) {
            return this;
        }

        // 移除指定事件下的所有监听器
        if (1 === arguments.length) {
            delete events[event];
            return this;
        }

        // 移除指定监听器（包括对once的处理）
        var cb;
        for (var i = 0; i < listeners.length; i++) {
            cb = listeners[i];
            if (cb === listener || cb.listener === listener) {
                listeners.splice(i, 1);
                break;
            }
        }
        return this;
    };

    /**
     * 触发事件
     *
     * @public
     * @param {string} event 事件名
     * @param {...*} args 传递给监听器的参数，可以有多个
     * @return {Emitter}
     */
    proto.emit = function (event) {
        var events = this._getEvents();
        var listeners = events[event];
        var args = Array.prototype.slice.call(arguments, 1);

        if (listeners) {
            listeners = listeners.slice(0);
            for (var i = 0, len = listeners.length; i < len; i++) {
                listeners[i].apply(this, args);
            }
        }

        return this;
    };

    /**
     * 返回指定事件的监听器列表
     *
     * @public
     * @param {string} event 事件名
     * @return {Array} 监听器列表
     */
    proto.listeners = function (event) {
        var events = this._getEvents();
        return events[event] || [];
    };

    /**
     * 设置监听器的最大个数，为0时不限制
     *
     * @param {number} number 监听器个数
     * @return {Emitter}
     */
    proto.setMaxListeners = function (number) {
        this.maxListeners = number;

        return this;
    };

    /**
     * 将Emitter混入目标对象
     *
     * @param {Object} obj 目标对象
     * @return {Object} 混入Emitter后的对象
     */
    Emitter.mixin = function (obj) {
        for (var key in Emitter.prototype) {
            obj[key] = Emitter.prototype[key];
        }
        return obj;
    };

    // Export
    if (typeof exports === 'object' && typeof module === 'object') {
        exports = module.exports = Emitter;
    }
    else if (typeof define === 'function' && define.amd) {
        define(function () {
            return Emitter;
        });
    }

})();

@@ -3259,60 +3259,153 @@
     
-var args = Array.prototype.slice.call(arguments, 1);
+// %E5%86%85%E8%81%94arguments%E7%9A%84%E8%BD%AC%E5%8C%96 %E6%8F%90%E5%8D%87%E6%80%A7%E8%83%BD%0A        var args = %5B%5D;%0A        for (var i = 1; i %3C arguments.length; i++) %7B%0A            args.push(arguments%5Bi%5D);%0A        %7D
 %0A%0A  
@@ -3492,24 +3492,18 @@
 or (
-var 
 i = 0
-, len =
+; i %3C
  lis
@@ -3520,17 +3520,8 @@
 gth;
- i %3C len;
  i++
@@ -4086,32 +4086,73 @@
 n this;%0A    %7D;%0A%0A
+    var protoKeys = Object.keys(proto);%0A%0A
     /**%0A     * %E5%B0%86
@@ -4299,44 +4299,137 @@
     
-for (var key in Emitter.prototype) %7B
+// forIn%E4%B8%8D%E5%88%A9%E4%BA%8EV8%E7%9A%84%E4%BC%98%E5%8C%96%0A        var key;%0A        for (var i = 0, max = protoKeys.length; i %3C max; i++) %7B%0A            key = protoKeys%5Bi%5D;
 %0A   
@@ -4448,33 +4448,21 @@
 %5Bkey%5D = 
-Emitter.
 proto
-type
 %5Bkey%5D;%0A 

Optimize performance