Object、Function、String、Array原生对象扩展方法
JavaScript原生对象的api有些情况下使用并不方便,考虑扩展基于Object、Function、String、Array扩展,参考了prototype.js的部分实现,做了提取和修改,分享下:
/** * * @authors yinshen (shenyin19861216@163.com) * @date 2013-09-05 23:23:25 * @version $Id$ */ //Object 扩展 (function() { var FUNCTION_CLASS = '[object Function]', BOOLEAN_CLASS = '[object Boolean]', NUMBER_CLASS = '[object Number]', STRING_CLASS = '[object String]', ARRAY_CLASS = '[object Array]', OBJECT_CLASS = '[object Object]', DATE_CLASS = '[object Date]'; function extend(destination, source) { for (var property in source) { destination[property] = source[property]; } return destination; } function clone(o,deep) { if (deep === true) { var target = {}; for (var property in o) { if (o.hasOwnProperty(property)) { if (Object.isObject(o[property])) { target[property] = Object.clone(o[property],true); } else { target[property] = o[property]; } } } return target; } else { return extend({}, o); } } function isElement(object) { return !!(this && object.nodeType == 1); } function isObject(object) { return Object.prototype.toString.call(object) === OBJECT_CLASS; } function isArray(object) { return Object.prototype.toString.call(object) === ARRAY_CLASS; } function isFunction(object) { return Object.prototype.toString.call(object) === FUNCTION_CLASS; } function isString(object) { return Object.prototype.toString.call(object) === STRING_CLASS; } function isNumber(object) { return Object.prototype.toString.call(object) === NUMBER_CLASS; } function isDate(object) { return Object.prototype.toString.call(object) === DATE_CLASS; } function isUndefined(object) { return typeof object === "undefined"; } function param(object) { var arr = []; for (var prop in object) { if (object.hasOwnProperty(prop)) { arr.push([encodeURIComponent(prop), "=", encodeURIComponent(object[prop]), "&"].join("")); } } return arr.join("").slice(0, -1); } function each(object,fn) { if(typeof fn ==="undefined"){return;} for (var prop in object) { if (object.hasOwnProperty(prop)) { if (fn(object[prop], prop) === false) { break; } } } } extend(Object, { //extend(Object.prototype, { extend: extend, clone: clone, isObject: isObject, isElement: isElement, isArray: isArray, isFunction: isFunction, isString: isString, isNumber: isNumber, isDate: isDate, isUndefined: isUndefined, param: param, each: each }); })(); //String 扩展 Object.extend(String.prototype, (function() { //字符串替换,支持{}和[] function format(o) { return this.replace(/\{(\w+)\}/g, function($1, $2) { return o[$2] !== undefined ? o[$2] : $1; }); }; //获取字符串长度,区分中文占2个字符 function len() { return this.replace(/[^\x00-\xff]/g, '**').length; } function truncate(length, truncation) { length = length || 30; truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); } function trim(isLeft) { if (isLeft === true) { return this.replace(/^\s+/, ''); } else if (isLeft === false) { return this.replace(/\s+$/, ''); } return this.replace(/^\s+/, '').replace(/\s+$/, ''); } var htmlDiv=document.createElement("div"); function html(escape) { /* var replace = ["'", "'", '"', """, " ", " ", ">", ">", "<", "<", "&", "&", ]; escape === false && replace.reverse(); for (var i = 0, str = this; i < replace.length; i += 2) { str = str.replace(new RegExp(replace[i], 'g'), replace[i + 1]); } return str;*/ function encode(){ htmlDiv.innerHTML=""; return htmlDiv.appendChild(document.createTextNode(this)).parentNode.innerHTML.replace(/\s/g, " "); } function decode(){ htmlDiv.innerHTML=this; return htmlDiv.innerText; } var str=this; return escape===false?decode.apply(str):encode.apply(str); } function has(pattern) { return this.indexOf(pattern) > -1; } function startsWith(pattern) { return this.lastIndexOf(pattern, 0) === 0; } function endsWith(pattern) { var d = this.length - pattern.length; return d >= 0 && this.indexOf(pattern, d) === d; } function empty() { return this == ''; } function text() { return this.replace(/<\/?[^>]*\/?>/g, ''); } function blank() { return /^\s*$/.test(this); } function sprintf(){ var i, result = this, param, reg, length = arguments.length; if (length < 1){ return text; } i = 0; while(i < length){ result = result.replace(/%s/, '{#' + (i++) + '#}'); } result.replace('%s', ''); i = 0; while( (param = arguments[i])!==undefined ){ // 0 也是可能的替换数字 reg = new RegExp('{#' + i + '#}', 'g') result = result.replace(reg, param); i++; } return result; } function bytes() { var str = this, i = 0, _char, l = 0; while(_char = str.charAt(i++)){ l += (_char).charCodeAt().toString(16).length / 2; } return l; } return { format: format, sprintf:sprintf, text: text, len: len, truncate: truncate, trim: String.prototype.trim || trim, html: html, //"&<>".html()==="&<>" "&<>".html(false)==="&<>" has: has, startsWith: startsWith, endsWith: endsWith, empty: empty, //内容为空,连空格都没 " ".empty()===false blank: blank, //没有任何有意义的字符,空格不算 " ".blank()===true bytes : bytes //计算一个字符串的字节长度 }; })()); //Function 扩展 Object.extend(Function.prototype, (function() { var slice = Array.prototype.slice; function update(array, args) { var arrayLength = array.length, length = args.length; while (length--) array[arrayLength + length] = args[length]; return array; } function merge(array, args) { array = slice.call(array, 0); return update(array, args); } function bind(context) { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; var __method = this, args = slice.call(arguments, 1); return function() { var a = merge(args, arguments); return __method.apply(context, a); } } /* 这东西炫耀的价值大于实用,还是不引入了 function curry() { if (!arguments.length) return this; var __method = this, args = slice.call(arguments, 0); return function() { var a = merge(args, arguments); return __method.apply(this, a); } } function uncurry(){ var __method=this; return function(){ Function.prototype.call.apply(__method,arguments); } }*/ function delay(timeout) { var __method = this, args = slice.call(arguments, 1); timeout = timeout * 1000; return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); } function defer() { var args = update([0.01], arguments); return this.delay.apply(this, args); } function before(fn) { var __method = this; return function() { if (fn.apply(this, arguments) === false) { return false; } return __method.apply(this, arguments); } } function after(fn) { var __method = this; return function() { var ret = __method.apply(this, arguments); var args = update([ret], arguments); fn.apply(this, args); return ret; } } function wrap(wrapper) { var __method = this; return function() { var a = update([__method.bind(this)], arguments); return wrapper.apply(this, a); } } return { bind: bind, delay: delay, defer: defer, before: before, after: after, wrap: wrap } })()); //Array扩展 (function() { var arrayProto = Array.prototype, slice = arrayProto.slice; function each(iterator, context) { for (var i = 0, length = this.length >>> 0; i < length; i++) { if (i in this) iterator.call(context, this[i], i, this); } } function last() { return this[this.length - 1]; } function clone(deep) { if (deep === true) { return Object.clone.apply(this, arguments); } return slice.call(this, 0); } function map(fn) { var arr = []; this.each(function(v, k) { arr.push( fn(v, k) ); }); return arr; } Object.extend(arrayProto, { each: Array.prototype.forEach || each, last: last, clone: clone, map: map }); })();