Js中經常使用的字符串,數組,函數擴展

因爲最近辭職在家,本身的時間相對多一點。因此就根據prototytpeJS的API,結合本身正在看的司徒大神的《javascript框架設計》,整理了下Js中經常使用一些字符串,數組,函數擴展,一來能夠練練手,二來也鍛鍊下本身的代碼能力。因爲代碼裏面的註釋自認爲已經很是詳細,因此就直接貼代碼了。javascript

1. 字符串擴展:html

;(function() {

    var method, stringExtends = {

        /**
         * 刪除字符串開始和結尾的空白
         * @returns {string}
         */
        strip: function() {
            return this.replace(/^\s+|\s+$/gm, '');
        },

        /**
         * 刪除字符串左邊的空白
         * @returns {string}
         */
        stripLeft: function() {
            return this.replace(/^\s+/, '');
        },

        /**
         * 刪除字符右邊的空白
         * @returns {string}
         */
        stripRight: function() {
            return this.replace(/\s+$/, '')
        },

        /**
         * 判斷一個字符串是不是空串;空串或只包含空白字符時返回true
         * @returns {boolean}
         */
        blank: function() {
            return this.strip().length === 0;
        },

        /**
         * 將CSS中屬性名轉換成JS中的樣式名,background-color -> backgroundColor
         * @returns {string}
         */
        camelize: function() {
            return this.replace(/(\-\w)/g, function(match) {
                return match.slice(1).toUpperCase();
            })
        },

        /**
         * 將一個字符串的首字母大寫,其它字符小寫
         * @returns {string}
         */
        capitalize: function() {
            return this.strip().replace(/^(\w{1})(.*)/g, function(match, g1, g2) {
                return g1.toUpperCase() + g2.toLowerCase();
            });
        },

        /**
         * 將字符串中的下劃線轉換成中劃線
         * @returns {string}
         */
        dasherize: function() {
            return this.replace(/\_/g, '-');
        },

        /**
         * 檢測字符串是不是空串
         * @returns {boolean}
         */
        empty: function() {
            return this.length === 0;

           /* ''.empty(); //-> true
            '  '.empty();//-> false*/
        },

        /**
         * 檢測字符串是不是以特定的字符串結尾
         * @param {String} target
         * @returns {boolean}
         */
        endsWith: function(target) {
            return (new RegExp(target+'$')).test(this);
            //return this.slice(-target.length) === target;
        },

        /**
         * 檢測字符串是不是以特定的字符串開始
         * @param {String} target
         * @returns {boolean}
         */
        startsWith: function(target) {
            return (new RegExp('^'+target)).test(this);
        },

        /**
         * 檢測字符串是否包含特定的字符串
         * @param {String} target
         * @returns {boolean}
         */
        contains: function(target) {
            return this.indexOf(target) !== -1;
        },

        /**
         *
         * @param {number} n - 要重複的次數
         * @returns {string}
         */
        times: function(n) {
            //return new Array(n+1).join(this);

            /*return [].join.call({
                length:n + 1
            }, this);*/

            //使用二分法
            var ret, flag = false, str = this.toString();
            if(n === 0)
                return '';
            if(n === 1)
                return str;
            if(n % 2) {
                //奇數
                n = n - 1;
                flag = true;
            }
            ret = str.times(n / 2);
            return flag ? (ret + ret + str) : (ret + ret);
        },

        /**
         * 對字符串中的特殊字符進行轉義,避免XSS
         */
        escapeHTML:function() {
            //轉義後的字符是能夠直接設置成innerHTML的值。
            //replace(/&/g, '&')這條replace()調用必定要寫在全部的特殊字符轉義的前面,否則轉換後有&符號的會再被轉一次
            return this.replace(/&/g, '&')
                    .replace(/\</g, '&lt;')
                    .replace(/\>/g, '&gt;')
                    .replace(/\'/g, '&#39;')
                    .replace(/\"/g, '&quot;');

            /*var strArr = this.split('');
            for(var pos = 0, l = strArr.length, tmp; pos < l; pos++) {
                tmp = strArr[pos];
                switch(tmp) {
                    case '<':
                        replaceArr(strArr, pos, '&lt;');
                        break;
                    case '>':
                        replaceArr(strArr, pos, '&gt;');
                        break;
                    case '\'':
                        replaceArr(strArr, pos, '&#39;');
                        break;
                    case '\"':
                        replaceArr(strArr, pos, '&quot;');
                        break;
                    case '&':
                        replaceArr(strArr, pos, '&amp;');
                        break;
                    default:;
                }
            }

            return strArr.join('');

            function replaceArr(arr, pos, item) {
                return arr.splice(pos, 1, item);
            }*/
        },

        /**
         * 對字符串進行反轉義
         */
        unescapeHTML: function() {
            return this.replace(/&amp;/, '&')
                .replace(/&lt;/g, '<')
                .replace(/&gt;/g, '>')
                .replace(/&#39;/g, '\'')
                .replace(/&quot;/g, '\"')
                .replace(/&#(\d+)/g, function($0, $1) {
                    return String.formCharCode(parseInt($1, 10));
                });
        },

        /**
         * 取得字符串的逆序
         * @returns {string}
         */
        reverse: function() {
            return (this.toString()).split('').reverse().join('');
        },

        /**
         * 截取字符串,並能夠指定填充後綴
         * @param {number} [length = 30] - 截取長度,默認爲30個字符
         * @param {string} [suffix = '...'] - 填充後綴,默認爲'...'
         * @returns {string}
         */
        truncate: function(length, suffix) {
            var ret = this.toString();
            length = length || 30;
            suffix = suffix || '...';

            //若是字符串不大於length, 直接返回字符串
            if(ret.length < length) {
                return ret;
            }

            return ret.slice(0, length - suffix.length) + suffix;
        },

        /**
         * 去掉字符串中的html標籤
         * @returns {string}
         */
        stripTags: function() {
            return this.replace(/(\<\w+\s?.*?\>)|(\<\/\w+\s?.*?\>)/g, function() {
                return '';
            });
        },

        /**
         * 去掉字符串中的腳本
         * @returns {string}
         */
        stripScripts: function() {
            return this.replace(/\<script\>.*?\<\/script\>/, function() {
                return '';
            })
        }


    };

    for(method in stringExtends) {
        stringExtends.hasOwnProperty(method) &&
        typeof String.prototype[method] !== 'function' &&
        (String.prototype[method] = stringExtends[method]);
    }

})();

 

2. 數組擴展java

 

;(function() {

    var method, arrayExtends = {

        /**
         * 爲數組增長ES5中的迭代方法:forEach, map, filter, every, some
         * W3C標準規定:每一個方法接收兩個參數,要在每一項上運行的回調和(可選的)運行回調時函數的上下文
         * 其中回調函數的參數中會包含三個參數:數組項的值,位置,和數組自己
         */


        /**
         * 對數組的每一項執行回調,這個方法沒返回值
         */
        forEach: function(fn, ctx) {
            for(var i = 0, l = this.length; i < l; i++) {
                fn.call(ctx || null, this[i], i, this);
            }
        },

        /**
         * 對數組每項運行回調函數,返回由回調函數的結果組成的數組
         */
        map: function(fn, ctx) {
            var ret = [];
            for(var i = 0, l = this.length; i < l; i++) {
                ret.push(fn.call(ctx || null, this[i], i, this));
            }
            return ret;
        },

        /**
         * 對數組每項運行回調函數,返回使回調函數返回值爲true組成的數組
         */
        filter: function(fn, ctx) {
            var ret = [];
            for(var i = 0, l = this.length; i < l; i++) {
                fn.call(ctx || null, this[i], i, this) &&
                ret.push(this[i]);
            }
            return ret;
        },

        /**
         * 對數組每項運行回調函數,若是全部的回調函數都返回true, 則返回true
         */
        every: function(fn, ctx) {
            for(var i = 0, l = this.length; i < l; i++) {
                !!fn.call(ctx || null, this[i], i, this) === false;
                return false;
            }
            return true;
        },

        /**
         * 對數組每項運行回調函數,若是有一項回調函數返回true, 則返回true
         */
        some: function(fn, ctx) {
            for(var i = 0, l = this.length; i < l; i++) {
                !!fn.call(ctx || null, this[i], i, this) === true;
                return true;
            }
            return false;
        },

        /**
         * 從左向右(順利)對數組的每一項(從第二項開始,即下標爲1)運行回調函數。
         * 回調函數包含四個參數prev(上一次回調的返回值), cur(當前數組項), index(當前數組項的索引), self(數組自己)
         * @param {Function} callback
         * @returns {*}
         */
        reduce: function(callback) {
            var i = 1, //從數組第二個元素開始
                l = this.length,
                callbackRet = this[0];
            for(; i < l; ++i) {
                callbackRet = callback.call(null, callbackRet, this[i], i, this);
            }

            return callbackRet;
        },

        /**
         * 從右向左(逆序)對數組的每一項(從倒數第二項開始,即下標爲arr.length - 2)運行回調函數。
         * 回調函數包含四個參數prev(上一次回調的返回值), cur(當前數組項), index(當前數組項的索引), self(數組自己)
         * @param {Function} callback
         * @returns {*}
         */
        reduceRight: function(callback) {
            var l = this.length,
                i = l - 2, //從數組倒數第二個元素開始
                callbackRet = this[l - 1]; //回調初始值爲數組最後一個元素的值
            for(; i >= 0; --i) {
                callbackRet = callback.call(null, callbackRet, this[i], i, this);
            }

            return callbackRet;
        },

        /**
         * 返回目標值在數組中第一次出現的位置,搜索從左向右進行。
         * 若是目標值在數組中不存在,則返回-1。能夠指定一個搜索起始位置。默認爲0
         * @param {Number} target
         * @param {Number} [start = 0] - start默認爲0
         * @returns {Number}
         */
        indexOf: function(target, start) {
            var l = this.length,
                start = ~~start;//能夠指定一個搜索起始位置。默認爲0。start不傳,默認爲undefined,~~undefined -> 0
            if(start < 0)
                start = 0;//若是指定的搜索位置小於0,則設置其開始搜索位置爲0
            for(; start < l; ++start) {
                if(this[start] === target)
                    return start;
            }
            return -1;
        },

        /**
         * 返回目標值在數組中的位置。搜索從右向左進行
         * 若是目標值在數組中不存在,則返回-1。能夠指定一個搜索起始位置。默認爲數組長度
         * @param {Number} target
         * @param {Number} [start = arr.length] - 開始搜索位置默認爲數組長度
         * @returns {Number}
         */
        lastIndexOf: function(target, start) {
            var l = this.length;
            if(start === void 0)
                start = this.length;
            else if(start < 0)
                start = 0;

            for(;start >= 0; --start) {
                if(this[start] === target)
                    return start;
            }
            return -1;
        },

        /**
         * 數組去重
         * @returns {Array}
         */
        unique: function() {
            var i = 0, j,
                l = this.length;

            for(; i < l; ++i) {
                for(j = i+1; j < l; j++) {
                    if(this[i] === this[j]) {
                        this.splice(j, 1);//把位置j的數組項刪除
                    }
                }
            }

            return this;
        },

        /**
         * 對於單一類型的數組,可使用此方法去重。
         * 但這類數組:[ 'ff', 1, '1' ]會去重失敗
         * @returns {Array}
         */
        enhanceUnique: function() {
            var ret = [], tempMap = {}, temp, i = 0, l = this.length, undef = void 0;
            for(; i < l; ++i) {
                temp = this[i];
                if(tempMap[temp] === undef) {
                    ret.push(temp);
                    tempMap[temp] = true;
                }
            }

            return ret;
        },

        /**
         * 去掉數組中的目標元素
         * @param value
         * @returns {Array}
         */
        without: function() {
            var args = [].slice.call(arguments).unique(),
                i = 0, l = this.length,
                j = 0, k = args.length;

            for(; i < l; ++i) {
                for(; j < k; ++j) {
                    if(this[i] === args[j]) {
                        this.splice(i, 1);
                    }
                }
                j = 0;//將j歸0,以便下次循環
            }

            return this;
        },

        /**
         * 遞歸將數組扁平化
         * @returns {Array}
         */
        flatten: function() {
            var ret = [], i = 0, l = this.length, tmp, toString = ({}).toString;

            for(; i < l; ++i) {
                tmp = this[i];
                if(toString.call(tmp) === '[object Array]') {
                    ret = ret.concat(tmp.flatten());
                } else {
                    ret.push(tmp);
                }
            }

            return ret;
        },

        /**
         * 隨機返回數組的一項
         * @returns {*}
         */
        random: function(n) {
            //Math.floor():向下取整。Math.floor(1.8) -> 1
            //Math.ceil():向上取整。Math.ceil(1.1) -> 2
            //v = Math.random() * n:會產生一個 0 < v < nv的數
            //v2 = Math.floor(Math.random() * n):v2爲一個大於等於0,小於n的整數
            return this[Math.floor(Math.random() * n || this.length)];
        },

        /**
         * 刪除數組指定位置的項
         * @returns {Array}
         */
        removeAt: function(pos) {
            this.splice(pos, 1);
            return this;
        },

        /**
         * 檢測數組是否包含目標值
         * @returns {Boolean}
         */
        contains: function(target) {
            return this.some(function(e, i, self) {
                return e === target;
            });
        },

        //數組的交,並,差集

        /**
         * 返回數組與目標數組的交集組成的數組
         * @returns {Array || null}
         */
        intersect: function(target) {
            var originalArr = this.unique(),
                target = target.unique();

            return originalArr.filter(function(e, i, self) {
                for( var i = 0, l = target.length; i < l; ++i) {
                    if(e === target[i]) {
                        return true;
                    }
                }
                return false;
            });
        },

        /**
         * 返回數組與目標數組的並集組成的數組
         * @returns {Array || null}
         */
        union: function(target) {
            return this.concat(target).unique();
        },


        /**
         * 返回數組與目標數組的差集組成的數組
         * @returns {Array || null}
         */
        diff: function(target) {
            var originalArr = this.unique(),
                target = target.unique();

            return originalArr.filter(function(e, i, self) {
                for( var i = 0, l = target.length; i < l; ++i) {
                    if(e === target[i]) {
                        return false;
                    }
                }
                return true;
            });
        },

        /**
         * 將數組清空,並返回這個數組的引用
         * @returns {Array}
         */
        clear: function() {
            this.length = 0;
            return this;
        },

        clone: function() {
            return [].concat(this);
        },

        /**
         * 去掉數組中的undefined, null
         * @returns {Array}
         */
        compact: function() {
            for(var i = 0, l = this.length; i < l; i++) {
                if(this[i] == null)
                    //刪除這個位置的元素
                    this.splice(i, 1);
            }
            return this;
        },

        /**
         * 返回數組第一項
         * @returns {*}
         */
        first: function() {
            return this[0];
        },

        /**
         * 返回數組最後一項
         * @returns {*}
         */
        last: function() {
            return this[this.length - 1];
        },

        /**
         * 返回數組的大小,即數組長度
         * @returns {Number}
         */
        size: function() {
            return this.length;
        }

    };

    for(method in arrayExtends) {
        arrayExtends.hasOwnProperty(method) &&
        typeof Array.prototype[method] !== 'function' &&
        (Array.prototype[method] = arrayExtends[method]);
    }

})();

 

3. 函數擴展api

;(function() {

    var method, functionExtends = {

        /**
         * 會返回一個函數:
         * 1. 這個函數被設置了做用域,即this值
         * 2. 若是運行bind()時有傳除this外的其它參數,則此函數還會包含這些參數。
         * 這些參數會與bind()返回的函數在運行時傳進來的參數共同組成返回函數的參數
         * @param {*} oThis - 要給函數綁定的做用域
         * @returns {Function}
         */

        bind: function(oThis) {
            var _slice = [].slice,
                args = _slice.call(arguments, 1),//運行bind()方法時要閉包保存的參數
                method = this;//要實際運行的函數
            return function() {
                return method.apply(oThis, args.concat(_slice.call(arguments)));
            }
        },

        /**
         * 函數curry是參數的一種處理,它能夠更加靈活地控制參數。
         * 關鍵點是何時返回函數繼續增長參數,何時要執行函數返回結果。
         * 要解決上面的問題能夠在curry時引入一個變量,手動設置最少須要的參數個數。
         * @param {Number} [minArgsNumber = 0] - 默認不須要任何參數
         * @returns {*}
         */
        curry: function(minArgsNumber) {
            var _slice = [].slice,
                closureArgs = _slice.call(arguments, 1),
                method = this,
                totalArgs;
            //minArgsNumber = arguments.length ? arguments[0] : 0;
            minArgsNumber = typeof minArgsNumber === 'number' ? minArgsNumber : 0;

            return function inner() {
                //究竟是執行函數,仍是繼續等待傳參由minArgsNumber決定
                totalArgs = typeof totalArgs === 'undefined' ?
                    closureArgs.concat(_slice.call(arguments)) :
                    totalArgs.concat(_slice.call(arguments));
                if(totalArgs.length >= minArgsNumber) {
                    //執行函數
                    return method.apply(this, totalArgs);
                } else {
                    //繼續返回函數接收參數
                    return inner;
                }
            }

        },

        /**
         * 以數組的形式返回函數的參數名字字符串。沒有參數時返回空數組
         * @returns {Array}
         */
        argumentNames: function() {
            var ret,
                methodCode = this.toString();
                methodCode.replace(/\((.*?)\)//*gm 函數裏面的代碼也可能會有(abc)字符串*/, function(match, g1) {
                    var argStr = g1.replace(/\s/g, '');
                    ret = argStr.length ? argStr.split(',') : [];
                });
            return ret;
        },

        /**
         * setTimeout的偷懶寫法
         */
        delay: function(delay) {
            var _slice = [].slice,
                method = this,
                closureArgs = _slice.call(arguments, 1);
            setTimeout(function() {
                method.apply(this, closureArgs.concat(_slice.call(arguments)));
            }, delay);
        }

    };

    for(method in functionExtends) {
        functionExtends.hasOwnProperty(method) &&
        typeof Function.prototype[method] !== 'function' &&
        (Function.prototype[method] = functionExtends[method]);
    }

})();

 

寫在最後:裏面有許多方法和思路都來至網上或《JavaScript框架設計》,都在此表示感謝。數組

相關文章
相關標籤/搜索