cocosjs源码阅读1-工具函数

/**

* Iterate over an object or an array, executing a function for each matched element.

* @param {object|array} obj

* @param {function} iterator

* @param {object} [context]

*/

cc.each = function (obj, iterator, context) {

    if (!obj)

        return;

    if (obj instanceof Array) {

        for (var i = 0, li = obj.length; i < li; i++) {

            if (iterator.call(context, obj[i], i) === false)

                return;

        }

    } else {

        for (var key in obj) {

            if (iterator.call(context, obj[key], key) === false)

                return;

        }

    }

};

/**

* Copy all of the properties in source objects to target object and return the target object.

* @param {object} target

* @param {object} *sources

* @returns {object}

*/

cc.extend = function (target) {

    var sources = arguments.length >= 2 ? Array.prototype.slice.call(arguments, 1) : [];

    cc.each(sources, function (src) {

        for (var key in src) {

            if (src.hasOwnProperty(key)) {

                target[key] = src[key];

            }

        }

    });

    return target;

};

/**

* Another way to subclass: Using Google Closure.

* The following code was copied + pasted from goog.base / goog.inherits

* @function

* @param {Function} childCtor

* @param {Function} parentCtor

*/

cc.inherits = function (childCtor, parentCtor) {

    function tempCtor() {}

    tempCtor.prototype = parentCtor.prototype;

    childCtor.superClass_ = parentCtor.prototype;

    childCtor.prototype = new tempCtor();

    childCtor.prototype.constructor = childCtor;

    // Copy "static" method, but doesn't generate subclasses.

    // for( var i in parentCtor ) {

    // childCtor[ i ] = parentCtor[ i ];

    // }

};

/**

* Check the obj whether is function or not

* @param {*} obj

* @returns {boolean}

*/

cc.isFunction = function (obj) {

    return typeof obj === 'function';

};

/**

* Check the obj whether is number or not

* @param {*} obj

* @returns {boolean}

*/

cc.isNumber = function (obj) {

    return typeof obj === 'number' || Object.prototype.toString.call(obj) === '[object Number]';

};

/**

* Check the obj whether is string or not

* @param {*} obj

* @returns {boolean}

*/

cc.isString = function (obj) {

    return typeof obj === 'string' || Object.prototype.toString.call(obj) === '[object String]';

};

/**

* Check the obj whether is array or not

* @param {*} obj

* @returns {boolean}

*/

cc.isArray = function (obj) {

    return Array.isArray(obj) ||

        (typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Array]');

};

/**

* Check the obj whether is undefined or not

* @param {*} obj

* @returns {boolean}

*/

cc.isUndefined = function (obj) {

    return typeof obj === 'undefined';

};

/**

* Check the obj whether is object or not

* @param {*} obj

* @returns {boolean}

*/

cc.isObject = function (obj) {

    return typeof obj === "object" && Object.prototype.toString.call(obj) === '[object Object]';

};

/**

* Check the url whether cross origin

* @param {String} url

* @returns {boolean}

*/

cc.isCrossOrigin = function (url) {

    if (!url) {

        cc.log("invalid URL");

        return false;

    }

    var startIndex = url.indexOf("://");

    if (startIndex === -1)

        return false;

    var endIndex = url.indexOf("/", startIndex + 3);

    var urlOrigin = (endIndex === -1) ? url : url.substring(0, endIndex);

    return urlOrigin !== location.origin;

};

//+++++++++++++++++++++++++something about async begin+++++++++++++++++++++++++++++++

/**

* Async Pool class, a helper of cc.async

* @param {Object|Array} srcObj

* @param {Number} limit the limit of parallel number

* @param {function} iterator

* @param {function} onEnd

* @param {object} target

* @constructor

*/

cc.AsyncPool = function (srcObj, limit, iterator, onEnd, target) {

    var self = this;

    self._finished = false;

    self._srcObj = srcObj;

    self._limit = limit;

    self._pool = [];

    self._iterator = iterator;

    self._iteratorTarget = target;

    self._onEnd = onEnd;

    self._onEndTarget = target;

    self._results = srcObj instanceof Array ? [] : {};

    self._errors = srcObj instanceof Array ? [] : {};

    cc.each(srcObj, function (value, index) {

        self._pool.push({index: index, value: value});

    });

    self.size = self._pool.length;

    self.finishedSize = 0;

    self._workingSize = 0;

    self._limit = self._limit || self.size;

    self.onIterator = function (iterator, target) {

        self._iterator = iterator;

        self._iteratorTarget = target;

    };

    self.onEnd = function (endCb, endCbTarget) {

        self._onEnd = endCb;

        self._onEndTarget = endCbTarget;

    };

    self._handleItem = function () {

        var self = this;

        if (self._pool.length === 0 || self._workingSize >= self._limit)

            return;                                                        //return directly if the array's length = 0 or the working size great equal limit number

        var item = self._pool.shift();

        var value = item.value, index = item.index;

        self._workingSize++;

        self._iterator.call(self._iteratorTarget, value, index,

            function (err, result) {

                if (self._finished) {

                    return;

                }

                if (err) {

                    self._errors[this.index] = err;

                }

                else {

                    self._results[this.index] = result;

                }

                self.finishedSize++;

                self._workingSize--;

                if (self.finishedSize === self.size) {

                    var errors = self._errors.length === 0 ? null : self._errors;

                    self.onEnd(errors, self._results);

                    return;

                }

                self._handleItem();

            }.bind(item),

            self);

    };

    self.flow = function () {

        var self = this;

        if (self._pool.length === 0) {

            if (self._onEnd)

                self._onEnd.call(self._onEndTarget, null, []);

            return;

        }

        for (var i = 0; i < self._limit; i++)

            self._handleItem();

    };

    self.onEnd = function(errors, results) {

        self._finished = true;

        if (self._onEnd) {

            var selector = self._onEnd;

            var target = self._onEndTarget;

            self._onEnd = null;

            self._onEndTarget = null;

            selector.call(target, errors, results);

        }

    };

};

/**

* @class

*/

cc.async = /** @lends cc.async# */{

    /**

    * Do tasks series.

    * @param {Array|Object} tasks

    * @param {function} [cb] callback

    * @param {Object} [target]

    * @return {cc.AsyncPool}

    */

    series: function (tasks, cb, target) {

        var asyncPool = new cc.AsyncPool(tasks, 1, function (func, index, cb1) {

            func.call(target, cb1);

        }, cb, target);

        asyncPool.flow();

        return asyncPool;

    },

    /**

    * Do tasks parallel.

    * @param {Array|Object} tasks

    * @param {function} cb callback

    * @param {Object} [target]

    * @return {cc.AsyncPool}

    */

    parallel: function (tasks, cb, target) {

        var asyncPool = new cc.AsyncPool(tasks, 0, function (func, index, cb1) {

            func.call(target, cb1);

        }, cb, target);

        asyncPool.flow();

        return asyncPool;

    },

    /**

    * Do tasks waterfall.

    * @param {Array|Object} tasks

    * @param {function} cb callback

    * @param {Object} [target]

    * @return {cc.AsyncPool}

    */

    waterfall: function (tasks, cb, target) {

        var args = [];

        var lastResults = [null];//the array to store the last results

        var asyncPool = new cc.AsyncPool(tasks, 1,

            function (func, index, cb1) {

                args.push(function (err) {

                    args = Array.prototype.slice.call(arguments, 1);

                    if (tasks.length - 1 === index) lastResults = lastResults.concat(args);//while the last task

                    cb1.apply(null, arguments);

                });

                func.apply(target, args);

            }, function (err) {

                if (!cb)

                    return;

                if (err)

                    return cb.call(target, err);

                cb.apply(target, lastResults);

            });

        asyncPool.flow();

        return asyncPool;

    },

    /**

    * Do tasks by iterator.

    * @param {Array|Object} tasks

    * @param {function|Object} iterator

    * @param {function} [callback]

    * @param {Object} [target]

    * @return {cc.AsyncPool}

    */

    map: function (tasks, iterator, callback, target) {

        var locIterator = iterator;

        if (typeof(iterator) === "object") {

            callback = iterator.cb;

            target = iterator.iteratorTarget;

            locIterator = iterator.iterator;

        }

        var asyncPool = new cc.AsyncPool(tasks, 0, locIterator, callback, target);

        asyncPool.flow();

        return asyncPool;

    },

    /**

    * Do tasks by iterator limit.

    * @param {Array|Object} tasks

    * @param {Number} limit

    * @param {function} iterator

    * @param {function} cb callback

    * @param {Object} [target]

    */

    mapLimit: function (tasks, limit, iterator, cb, target) {

        var asyncPool = new cc.AsyncPool(tasks, limit, iterator, cb, target);

        asyncPool.flow();

        return asyncPool;

    }

};

//+++++++++++++++++++++++++something about async end+++++++++++++++++++++++++++++++++

//+++++++++++++++++++++++++something about path begin++++++++++++++++++++++++++++++++

/**

* @class

*/

cc.path = /** @lends cc.path# */{

    normalizeRE: /[^\.\/]+\/\.\.\//,

    /**

    * Join strings to be a path.

    * @example

    cc.path.join("a", "b.png");//-->"a/b.png"

    cc.path.join("a", "b", "c.png");//-->"a/b/c.png"

    cc.path.join("a", "b");//-->"a/b"

    cc.path.join("a", "b", "/");//-->"a/b/"

    cc.path.join("a", "b/", "/");//-->"a/b/"

    * @returns {string}

    */

    join: function () {

        var l = arguments.length;

        var result = "";

        for (var i = 0; i < l; i++) {

            result = (result + (result === "" ? "" : "/") + arguments[i]).replace(/(\/|\\\\)$/, "");

        }

        return result;

    },

    /**

    * Get the ext name of a path.

    * @example

    cc.path.extname("a/b.png");//-->".png"

    cc.path.extname("a/b.png?a=1&b=2");//-->".png"

    cc.path.extname("a/b");//-->null

    cc.path.extname("a/b?a=1&b=2");//-->null

    * @param {string} pathStr

    * @returns {*}

    */

    extname: function (pathStr) {

        var temp = /(\.[^\.\/\?\\]*)(\?.*)?$/.exec(pathStr);

        return temp ? temp[1] : null;

    },

    /**

    * Get the main name of a file name

    * @param {string} fileName

    * @returns {string}

    */

    mainFileName: function (fileName) {

        if (fileName) {

            var idx = fileName.lastIndexOf(".");

            if (idx !== -1)

                return fileName.substring(0, idx);

        }

        return fileName;

    },

    /**

    * Get the file name of a file path.

    * @example

    cc.path.basename("a/b.png");//-->"b.png"

    cc.path.basename("a/b.png?a=1&b=2");//-->"b.png"

    cc.path.basename("a/b.png", ".png");//-->"b"

    cc.path.basename("a/b.png?a=1&b=2", ".png");//-->"b"

    cc.path.basename("a/b.png", ".txt");//-->"b.png"

    * @param {string} pathStr

    * @param {string} [extname]

    * @returns {*}

    */

    basename: function (pathStr, extname) {

        var index = pathStr.indexOf("?");

        if (index > 0) pathStr = pathStr.substring(0, index);

        var reg = /(\/|\\\\)([^(\/|\\\\)]+)$/g;

        var result = reg.exec(pathStr.replace(/(\/|\\\\)$/, ""));

        if (!result) return null;

        var baseName = result[2];

        if (extname && pathStr.substring(pathStr.length - extname.length).toLowerCase() === extname.toLowerCase())

            return baseName.substring(0, baseName.length - extname.length);

        return baseName;

    },

    /**

    * Get dirname of a file path.

    * @example

    * unix

    cc.path.driname("a/b/c.png");//-->"a/b"

    cc.path.driname("a/b/c.png?a=1&b=2");//-->"a/b"

    cc.path.dirname("a/b/");//-->"a/b"

    cc.path.dirname("c.png");//-->""

    * windows

    cc.path.driname("a\\b\\c.png");//-->"a\b"

    cc.path.driname("a\\b\\c.png?a=1&b=2");//-->"a\b"

    * @param {string} pathStr

    * @returns {*}

    */

    dirname: function (pathStr) {

        return pathStr.replace(/((.*)(\/|\\|\\\\))?(.*?\..*$)?/, '$2');

    },

    /**

    * Change extname of a file path.

    * @example

    cc.path.changeExtname("a/b.png", ".plist");//-->"a/b.plist"

    cc.path.changeExtname("a/b.png?a=1&b=2", ".plist");//-->"a/b.plist?a=1&b=2"

    * @param {string} pathStr

    * @param {string} [extname]

    * @returns {string}

    */

    changeExtname: function (pathStr, extname) {

        extname = extname || "";

        var index = pathStr.indexOf("?");

        var tempStr = "";

        if (index > 0) {

            tempStr = pathStr.substring(index);

            pathStr = pathStr.substring(0, index);

        }

        index = pathStr.lastIndexOf(".");

        if (index < 0) return pathStr + extname + tempStr;

        return pathStr.substring(0, index) + extname + tempStr;

    },

    /**

    * Change file name of a file path.

    * @example

    cc.path.changeBasename("a/b/c.plist", "b.plist");//-->"a/b/b.plist"

    cc.path.changeBasename("a/b/c.plist?a=1&b=2", "b.plist");//-->"a/b/b.plist?a=1&b=2"

    cc.path.changeBasename("a/b/c.plist", ".png");//-->"a/b/c.png"

    cc.path.changeBasename("a/b/c.plist", "b");//-->"a/b/b"

    cc.path.changeBasename("a/b/c.plist", "b", true);//-->"a/b/b.plist"

    * @param {String} pathStr

    * @param {String} basename

    * @param {Boolean} [isSameExt]

    * @returns {string}

    */

    changeBasename: function (pathStr, basename, isSameExt) {

        if (basename.indexOf(".") === 0) return this.changeExtname(pathStr, basename);

        var index = pathStr.indexOf("?");

        var tempStr = "";

        var ext = isSameExt ? this.extname(pathStr) : "";

        if (index > 0) {

            tempStr = pathStr.substring(index);

            pathStr = pathStr.substring(0, index);

        }

        index = pathStr.lastIndexOf("/");

        index = index <= 0 ? 0 : index + 1;

        return pathStr.substring(0, index) + basename + ext + tempStr;

    },

    //todo make public after verification

    _normalize: function (url) {

        var oldUrl = url = String(url);

        //removing all ../

        do {

            oldUrl = url;

            url = url.replace(this.normalizeRE, "");

        } while (oldUrl.length !== url.length);

        return url;

    }

};

你可能感兴趣的:(cocosjs源码阅读1-工具函数)