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 = ["'", "&#39;", '"', "&quot;", " ", "&nbsp;", ">", "&gt;", "<", "&lt;", "&", "&amp;", ];
        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, "&nbsp;");
        }

        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()==="&amp;&lt;&gt;"    "&amp;&lt;&gt;".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
    });
})();

 

posted on 2013-09-06 03:03  西瓜SY  阅读(492)  评论(0编辑  收藏  举报