因爲最近辭職在家,本身的時間相對多一點。因此就根據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, '<') .replace(/\>/g, '>') .replace(/\'/g, ''') .replace(/\"/g, '"'); /*var strArr = this.split(''); for(var pos = 0, l = strArr.length, tmp; pos < l; pos++) { tmp = strArr[pos]; switch(tmp) { case '<': replaceArr(strArr, pos, '<'); break; case '>': replaceArr(strArr, pos, '>'); break; case '\'': replaceArr(strArr, pos, '''); break; case '\"': replaceArr(strArr, pos, '"'); break; case '&': replaceArr(strArr, pos, '&'); break; default:; } } return strArr.join(''); function replaceArr(arr, pos, item) { return arr.splice(pos, 1, item); }*/ }, /** * 對字符串進行反轉義 */ unescapeHTML: function() { return this.replace(/&/, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/'/g, '\'') .replace(/"/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框架設計》,都在此表示感謝。數組