justin-zhengyi-wu / blogs

My Blogs
http://blog.justin4u.com/
4 stars 0 forks source link

Seajs 源码分析 1 #8

Open justin-zhengyi-wu opened 11 years ago

justin-zhengyi-wu commented 11 years ago

util-lang.js 有关JS语言增强

function isType(type) {
    return function(obj) {
        // 这里使用Object原型的toString方法来判断传入对象的类型.
        // {} - '[object Object]'
        // '' - '[object String]'
        // [] - '[object Array]'
        // function(){} - '[object Function]'
        return Object.prototype.toString.call(obj) === "[object " + type + "]"
    }
}

var isObject = isType("Object") 
var isString = isType("String")
// 如果JS宿主支持原生的Array.isArray方法, 优先使用
var isArray = Array.isArray || isType("Array")
var isFunction = isType("Function")

var _cid = 0
// 用来生成不重复的数字ID
function cid() {
    return _cid++
}

util-events.js 事件支持

// 定义变量events为一个空对象, 并赋给变量seajs.data.events
var events = data.events = {}

// 事件绑定
seajs.on = function(name, callback) {
    // 定义变量list, 如果事件列表中已经存在该事件的listeners, 设其为该事件上已绑定的listeners.
    // 如果事件列表中还没有该事件的listeners, 设置该事件上绑定的listeners为空数组, 并赋给变量list.
    var list = events[name] || (events[name] = [])
    // 将传入的监听器或者称之为回调函数加到当前事件的listeners.
    list.push(callback)
    // 返回对象seajs, 这样可以象jQuery一样链式调用.
    return seajs
}

// 事件移除.
// 如果传入事件名, 但未传入要移除的监听器, 将把事件name上所有的监听器都移除掉.
// 如果事件名和监听器都没有传入, 将把所有事件上的所有监听器都移除掉. Note: (危险操作, 需谨慎)
seajs.off = function(name, callback) {
    // 如果事件名和监听器都没有传入, 
    if (!(name || callback)) {
        // 将events和data.events置空
        events = data.events = {}
        // 返回对象seajs, 这样可以象jQuery一样链式调用.
        return seajs
    }

    // 获取当前事件name的监听器列表, 并赋值给变量list
    var list = events[name]
    // 如果当前事件name上有相应的监听器
    if (list) {
        // 如果传入的想要移除的监听器非空
        if(callback) {
            // 迭代所有的监听器
            for (var i = list.length - 1; i >= 0; i--) {
                // 如果发现其中有要移除的监听器
                if (list[i] === callback) {
                    // 把要移除的监听器从监听器列表中删去.
                    list.splice(i, 1)
                }
            }
        } else {
            // 如果没有传入的想要移除的监听器, 移除当前事件上所有的监听器.
            delete events[name]
        }
    }
    // 返回对象seajs以便链式调用.
    return seajs    
}

// 触发事件, 所有的监听器都会激活, 并且传入与emit方法相同的参数(不含事件名).
// 定义方法emit并传递给seajs.emit
var emit = seajs.emit = function(name, data) {
    // 定义变量list为当前事件name的所有监听器列表.
    // 定义变量fn为某个监听器
    var list = events[name], fn
    // 如果当前事件name上含有监听器
    if (list) {
        // 复制监听器列表以防止修改
        list = list.slice()
        // 迭代所有的监听器, 从中依次取出
        while ((fn = list.shift())) {
            // 执行取出的监听器, 传入与emit方法相同的参数(不含事件名)
            fn(data)
        }
    }
    // 返回对象seajs以便链式调用.
    return seajs
}