• QWrap简介之:Helper规范


    Helper规范是一个很简单轻松的规范,这个在core/js/helper.h.js里有提到。
    一个Helper是指同时满足如下条件的一个对象:
      1。Helper是一个不带有可枚举proto属性的简单对象(这意味着你可以用for...in...枚举一个Helper中的所有属性和方法)
      2。Helper可以拥有属性和方法,但Helper对方法的定义必须满足如下条件:
        2.1. Helper的方法必须是静态方法,即内部不能使用this。
        2.2. 同一个Helper中的方法的第一个参数必须是相同类型或相同泛型。

    也可以分拆成三点来描述:
      1。Helper是一个不带有可枚举proto属性的简单对象。 (纯洁)
      2。Helper的所有方法必须是静态方法,即内部不能使用this。 (静态)
      3。同一个Helper中的方法的第一个参数必须是相同类型或相同泛型。(针对性)

    QWrap中,一个Helper对应的命名空间通常以“H”结尾,对应的js通常以“.h.js”结尾。
    例如,QW.StringH是针对String的Helper的命名空间,它对应的js是“js/core/string.h.js”。
    对于只满足“纯洁”“静态”特征的对象,也算是泛Helper,命名空间以“U”(util)结尾。
    本来Util和Helper应该是继承关系,但是QWrap淡化了这些关系概念。


    “纯洁”有什么用?----方便以后for in。----顺便说一下QWrap的一个脆弱:如果有人把Object的原型污染掉了,可能会产生一些隐患。----同学们啦,千万别污染Object的原型。
    “静态”有什么用?----方便移植与函数变换。
    “针对性”有什么用?----方便分组,以及移植与函数变换。

    这里着重说一下“针对性”的意义。
    1 方便分组: 针对字符串的很多方法,就放在StringH里,例如trim、byteLen、subByte、encode4Html、encode4Js;而针对Array的,则放在ArrayH里,如forEach、map、filter。
    2 这些方法的第一个参数是它针对的变量。StringH里的所有方法的第一个参数都是字符串,而ArrayH里的所有方法的第一个参数都是数组或类数组(ArrayLike)。
    3 有了这种针对性,我们就可以找标准(包括理论标准与事实标准)来实现堆砌代码了,例如StringH.contains(s,subStr) ArrayH.contains(arr, obj) NodeH.contains(parentEl,subEl)。同样是contains,它们各有标准、各得其所、互不冲突。
    4 让批量转换有了理论依据。
    当然,“纯洁”“静态”“针对性”,这三点对于批量转换都很重要。

    好的,看几个Helper的实例,来感性的认识下Helper吧:
    string.h.js (针对String的Helper)
    View Code
    /**
    * @class StringH 核心对象String的扩展
    * @singleton
    * @namespace QW
    * @helper
    */

    (
    function() {

    var StringH = {
    /**
    * 除去字符串两边的空白字符
    * @method trim
    * @static
    * @param {String} s 需要处理的字符串
    * @return {String} 除去两端空白字符后的字符串
    * @remark 如果字符串中间有很多连续tab,会有有严重效率问题,相应问题可以用下一句话来解决.
    return s.replace(/^[\s\xa0\u3000]+/g,"").replace(/([^\u3000\xa0\s])[\u3000\xa0\s]+$/g,"$1");
    */
    trim:
    function(s) {
    return s.replace(/^[\s\xa0\u3000]+|[\u3000\xa0\s]+$/g, "");
    },
    /**
    * 对一个字符串进行多次replace
    * @method mulReplace
    * @static
    * @param {String} s 需要处理的字符串
    * @param {array} arr 数组,每一个元素都是由replace两个参数组成的数组
    * @return {String} 返回处理后的字符串
    * @example alert(mulReplace("I like aa and bb. JK likes aa.",[[/aa/g,"山"],[/bb/g,"水"]]));
    */
    mulReplace:
    function(s, arr) {
    for (var i = 0; i < arr.length; i++) {
    s
    = s.replace(arr[i][0], arr[i][1]);
    }
    return s;
    },
    /**
    * 字符串简易模板
    * @method format
    * @static
    * @param {String} s 字符串模板,其中变量以{0} {1}表示
    * @param {String} arg0 (Optional) 替换的参数
    * @return {String} 模板变量被替换后的字符串
    * @example alert(format("{0} love {1}.",'I','You'))
    */
    format:
    function(s, arg0) {
    var args = arguments;
    return s.replace(/\{(\d+)\}/ig, function(a, b) {
    return args[(b | 0) + 1] || '';
    });
    },

    /*
    * 字符串简易模板
    * @method tmpl
    * @static
    * @param {String} sTmpl 字符串模板,其中变量以{$aaa}表示
    * @param {Object} opts 模板参数
    * @return {String} 模板变量被替换后的字符串
    * @example alert(tmpl("{$a} love {$b}.",{a:"I",b:"you"}))
    tmpl:function(sTmpl,opts){
    return sTmpl.replace(/\{\$(\w+)\}/g,function(a,b){return opts[b]});
    },
    */

    /**
    * 字符串模板
    * @method tmpl
    * @static
    * @param {String} sTmpl 字符串模板,其中变量以{$aaa}表示。模板语法:
    分隔符为{xxx},"}"之前没有空格字符。
    js表达式/js语句里的'}', 需使用' }',即前面有空格字符
    {strip}...{/strip}里的所有\r\n打头的空白都会被清除掉
    {}里只能使用表达式,不能使用语句,除非使用以下标签
    {js ...} --任意js语句, 里面如果需要输出到模板,用print("aaa");
    {if(...)} --if语句,写法为{if($a>1)},需要自带括号
    {elseif(...)} --elseif语句,写法为{elseif($a>1)},需要自带括号
    {else} --else语句,写法为{else}
    {/if} --endif语句,写法为{/if}
    {for(...)} --for语句,写法为{for(var i=0;i<1;i++)},需要自带括号
    {/for} --endfor语句,写法为{/for}
    {while(...)} --while语句,写法为{while(i-->0)},需要自带括号
    {/while} --endwhile语句, 写法为{/while}
    * @param {Object} opts (Optional) 模板参数
    * @return {String|Function} 如果调用时传了opts参数,则返回字符串;如果没传,则返回一个function(相当于把sTmpl转化成一个函数)

    * @example alert(tmpl("{$a} love {$b}.",{a:"I",b:"you"}));
    * @example alert(tmpl("{js print('I')} love {$b}.",{b:"you"}));
    */
    tmpl: (
    function() {
    /*
    sArrName 拼接字符串的变量名。
    */
    var sArrName = "sArrCMX",
    sLeft
    = sArrName + '.push("';
    /*
    tag:模板标签,各属性含义:
    tagG: tag系列
    isBgn: 是开始类型的标签
    isEnd: 是结束类型的标签
    cond: 标签条件
    rlt: 标签结果
    sBgn: 开始字符串
    sEnd: 结束字符串
    */
    var tags = {
    'js': {
    tagG:
    'js',
    isBgn:
    1,
    isEnd:
    1,
    sBgn:
    '");',
    sEnd:
    ';' + sLeft
    },
    //任意js语句, 里面如果需要输出到模板,用print("aaa");
    'if': {
    tagG:
    'if',
    isBgn:
    1,
    rlt:
    1,
    sBgn:
    '");if',
    sEnd:
    '{' + sLeft
    },
    //if语句,写法为{if($a>1)},需要自带括号
    'elseif': {
    tagG:
    'if',
    cond:
    1,
    rlt:
    1,
    sBgn:
    '");} else if',
    sEnd:
    '{' + sLeft
    },
    //if语句,写法为{elseif($a>1)},需要自带括号
    'else': {
    tagG:
    'if',
    cond:
    1,
    rlt:
    2,
    sEnd:
    '");}else{' + sLeft
    },
    //else语句,写法为{else}
    '/if': {
    tagG:
    'if',
    isEnd:
    1,
    sEnd:
    '");}' + sLeft
    },
    //endif语句,写法为{/if}
    'for': {
    tagG:
    'for',
    isBgn:
    1,
    rlt:
    1,
    sBgn:
    '");for',
    sEnd:
    '{' + sLeft
    },
    //for语句,写法为{for(var i=0;i<1;i++)},需要自带括号
    '/for': {
    tagG:
    'for',
    isEnd:
    1,
    sEnd:
    '");}' + sLeft
    },
    //endfor语句,写法为{/for}
    'while': {
    tagG:
    'while',
    isBgn:
    1,
    rlt:
    1,
    sBgn:
    '");while',
    sEnd:
    '{' + sLeft
    },
    //while语句,写法为{while(i-->0)},需要自带括号
    '/while': {
    tagG:
    'while',
    isEnd:
    1,
    sEnd:
    '");}' + sLeft
    }
    //endwhile语句, 写法为{/while}
    };

    return function(sTmpl, opts) {
    var N = -1,
    NStat
    = []; //语句堆栈;
    var ss = [
    [
    /\{strip\}([\s\S]*?)\{\/strip\}/g, function(a, b) {
    return b.replace(/[\r\n]\s*\}/g, " }").replace(/[\r\n]\s*/g, "");
    }],
    [
    /\\/g, '\\\\'],
    [
    /"/g, '\\"'],
    [
    /\r/g, '\\r'],
    [
    /\n/g, '\\n'], //为js作转码.
    [
    /\{[\s\S]*?\S\}/g, //js里使用}时,前面要加空格。
    function(a) {
    a
    = a.substr(1, a.length - 2);
    for (var i = 0; i < ss2.length; i++) {a = a.replace(ss2[i][0], ss2[i][1]); }
    var tagName = a;
    if (/^(.\w+)\W/.test(tagName)) {tagName = RegExp.$1; }
    var tag = tags[tagName];
    if (tag) {
    if (tag.isBgn) {
    var stat = NStat[++N] = {
    tagG: tag.tagG,
    rlt: tag.rlt
    };
    }
    if (tag.isEnd) {
    if (N < 0) {throw new Error("多余的结束标记" + a); }
    stat
    = NStat[N--];
    if (stat.tagG != tag.tagG) {throw new Error("标记不匹配:" + stat.tagG + "--" + tagName); }
    }
    else if (!tag.isBgn) {
    if (N < 0) {throw new Error("多余的标记" + a); }
    stat
    = NStat[N];
    if (stat.tagG != tag.tagG) {throw new Error("标记不匹配:" + stat.tagG + "--" + tagName); }
    if (tag.cond && !(tag.cond & stat.rlt)) {throw new Error("标记使用时机不对:" + tagName); }
    stat.rlt
    = tag.rlt;
    }
    return (tag.sBgn || '') + a.substr(tagName.length) + (tag.sEnd || '');
    }
    else {
    return '",(' + a + '),"';
    }
    }
    ]
    ];
    var ss2 = [
    [
    /\\n/g, '\n'],
    [
    /\\r/g, '\r'],
    [
    /\\"/g, '"'],
    [
    /\\\\/g, '\\'],
    [
    /\$(\w+)/g, 'opts["$1"]'],
    [
    /print\(/g, sArrName + '.push(']
    ];
    for (var i = 0; i < ss.length; i++) {
    sTmpl
    = sTmpl.replace(ss[i][0], ss[i][1]);
    }
    if (N >= 0) {throw new Error("存在未结束的标记:" + NStat[N].tagG); }
    sTmpl
    = 'var ' + sArrName + '=[];' + sLeft + sTmpl + '");return ' + sArrName + '.join("");';
    //alert('转化结果\n'+sTmpl);
    var fun = new Function('opts', sTmpl);
    if (arguments.length > 1) {return fun(opts); }
    return fun;
    };
    }()),

    /**
    * 判断一个字符串是否包含另一个字符串
    * @method contains
    * @static
    * @param {String} s 字符串
    * @param {String} opts 子字符串
    * @return {String} 模板变量被替换后的字符串
    * @example alert(contains("aaabbbccc","ab"))
    */
    contains:
    function(s, subStr) {
    return s.indexOf(subStr) > -1;
    },

    /**
    * 全角字符转半角字符
    全角空格为12288,转化成" ";
    全角句号为12290,转化成".";
    其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
    * @method dbc2sbc
    * @static
    * @param {String} s 需要处理的字符串
    * @return {String} 返回转化后的字符串
    * @example
    var s="发票号是BBC123456,发票金额是12.35元";
    alert(dbc2sbc(s));
    */
    dbc2sbc:
    function(s) {
    return StringH.mulReplace(s, [
    [
    /[\uff01-\uff5e]/g, function(a) {
    return String.fromCharCode(a.charCodeAt(0) - 65248);
    }],
    [
    /\u3000/g, ' '],
    [
    /\u3002/g, '.']
    ]);
    },

    /**
    * 得到字节长度
    * @method byteLen
    * @static
    * @param {String} s 字符串
    * @return {number} 返回字节长度
    */
    byteLen:
    function(s) {
    return s.replace(/[^\x00-\xff]/g, "--").length;
    },

    /**
    * 得到指定字节长度的子字符串
    * @method subByte
    * @static
    * @param {String} s 字符串
    * @param {number} len 字节长度
    * @param {string} tail (Optional) 结尾字符串
    * @return {string} 返回指定字节长度的子字符串
    */
    subByte:
    function(s, len, tail) {
    if (StringH.byteLen(s) <= len) {return s; }
    tail
    = tail || '';
    len
    -= StringH.byteLen(tail);
    return s.substr(0, len).replace(/([^\x00-\xff])/g, "$1 ") //双字节字符替换成两个
    .substr(0, len) //截取长度
    .replace(/[^\x00-\xff]$/, "") //去掉临界双字节字符
    .replace(/([^\x00-\xff]) /g, "$1") + tail; //还原
    },

    /**
    * 驼峰化字符串。将“ab-cd”转化为“abCd”
    * @method camelize
    * @static
    * @param {String} s 字符串
    * @return {String} 返回转化后的字符串
    */
    camelize:
    function(s) {
    return s.replace(/\-(\w)/ig, function(a, b) {
    return b.toUpperCase();
    });
    },

    /**
    * 反驼峰化字符串。将“abCd”转化为“ab-cd”。
    * @method decamelize
    * @static
    * @param {String} s 字符串
    * @return {String} 返回转化后的字符串
    */
    decamelize:
    function(s) {
    return s.replace(/[A-Z]/g, function(a) {
    return "-" + a.toLowerCase();
    });
    },

    /**
    * 字符串为javascript转码
    * @method encode4Js
    * @static
    * @param {String} s 字符串
    * @return {String} 返回转化后的字符串
    * @example
    var s="my name is \"JK\",\nnot 'Jack'.";
    window.setTimeout("alert('"+encode4Js(s)+"')",10);
    */
    encode4Js:
    function(s) {
    return StringH.mulReplace(s, [
    [
    /\\/g, "\\u005C"],
    [
    /"/g, "\\u0022"],
    [
    /'/g, "\\u0027"],
    [
    /\//g, "\\u002F"],
    [
    /\r/g, "\\u000A"],
    [
    /\n/g, "\\u000D"],
    [
    /\t/g, "\\u0009"]
    ]);
    },

    /**
    * 为http的不可见字符、不安全字符、保留字符作转码
    * @method encode4Http
    * @static
    * @param {String} s 字符串
    * @return {String} 返回处理后的字符串
    */
    encode4Http:
    function(s) {
    return s.replace(/[\u0000-\u0020\u0080-\u00ff\s"'#\/\|\\%<>\[\]\{\}\^~;\?\:@=&]/, function(a) {
    return encodeURIComponent(a);
    });
    },

    /**
    * 字符串为Html转码
    * @method encode4Html
    * @static
    * @param {String} s 字符串
    * @return {String} 返回处理后的字符串
    * @example
    var s="<div>dd";
    alert(encode4Html(s));
    */
    encode4Html:
    function(s) {
    var el = document.createElement('pre'); //这里要用pre,用div有时会丢失换行,例如:'a\r\n\r\nb'
    var text = document.createTextNode(s);
    el.appendChild(text);
    return el.innerHTML;
    },

    /**
    * 字符串为Html的value值转码
    * @method encode4HtmlValue
    * @static
    * @param {String} s 字符串
    * @return {String} 返回处理后的字符串
    * @example:
    var s="<div>\"\'ddd";
    alert("<input value='"+encode4HtmlValue(s)+"'>");
    */
    encode4HtmlValue:
    function(s) {
    return StringH.encode4Html(s).replace(/"/g, "&quot;").replace(/'/g, "&#039;");
    },

    /**
    * 与encode4Html方法相反,进行反编译
    * @method decode4Html
    * @static
    * @param {String} s 字符串
    * @return {String} 返回处理后的字符串
    */
    decode4Html:
    function(s) {
    var div = document.createElement('div');
    div.innerHTML
    = StringH.stripTags(s);
    return div.childNodes[0] ? div.childNodes[0].nodeValue || '' : '';
    },
    /**
    * 将所有tag标签消除,即去除<tag>,以及</tag>
    * @method stripTags
    * @static
    * @param {String} s 字符串
    * @return {String} 返回处理后的字符串
    */
    stripTags:
    function(s) {
    return s.replace(/<[^>]*>/gi, '');
    },
    /**
    * eval某字符串。如果叫"eval",在这里需要加引号,才能不影响YUI压缩。不过其它地方用了也会有问题,所以改名evalJs,
    * @method evalJs
    * @static
    * @param {String} s 字符串
    * @param {any} opts 运行时需要的参数。
    * @return {any} 根据字符结果进行返回。
    */
    evalJs:
    function(s, opts) { //如果用eval,在这里需要加引号,才能不影响YUI压缩。不过其它地方用了也会有问题,所以改成evalJs,
    return new Function("opts", s)(opts);
    },
    /**
    * eval某字符串,这个字符串是一个js表达式,并返回表达式运行的结果
    * @method evalExp
    * @static
    * @param {String} s 字符串
    * @param {any} opts eval时需要的参数。
    * @return {any} 根据字符结果进行返回。
    */
    evalExp:
    function(s, opts) {
    return new Function("opts", "return (" + s + ");")(opts);
    }
    };

    QW.StringH
    = StringH;

    }());

    array.h.js (针对Array的Helper)
    View Code
    /**
    * @class ArrayH 核心对象Array的扩展
    * @singleton
    * @namespace QW
    * @helper
    */
    (
    function() {

    var ArrayH = {
    /**
    * 在数组中的每个项上运行一个函数,并将全部结果作为数组返回。
    * @method map
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数.
    * @param {Object} pThis (Optional) 指定callback的this对象.
    * @return {Array} 返回满足过滤条件的元素组成的新数组
    * @example
    var arr=["aa","ab","bc"];
    var arr2=map(arr,function(a,b){return a.substr(0,1)=="a"});
    alert(arr2);
    */
    map:
    function(arr, callback, pThis) {
    var len = arr.length;
    var rlt = new Array(len);
    for (var i = 0; i < len; i++) {
    if (i in arr) {
    rlt[i]
    = callback.call(pThis, arr[i], i, arr);
    }
    }
    return rlt;
    },

    /**
    * 对Array的每一个元素运行一个函数。
    * @method forEach
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数.
    * @param {Object} pThis (Optional) 指定callback的this对象.
    * @return {void}
    * @example
    var arr=["a","b","c"];
    var dblArr=[];
    forEach(arr,function(a,b){dblArr.push(b+":"+a+a);});
    alert(dblArr);
    */
    forEach:
    function(arr, callback, pThis) {
    for (var i = 0, len = arr.length; i < len; i++) {
    if (i in arr) {
    callback.call(pThis, arr[i], i, arr);
    }
    }
    },

    /**
    * 在数组中的每个项上运行一个函数,并将函数返回真值的项作为数组返回。
    * @method filter
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数.
    * @param {Object} pThis (Optional) 指定callback的this对象.
    * @return {Array} 返回满足过滤条件的元素组成的新数组
    * @example
    var arr=["aa","ab","bc"];
    var arr2=filter(arr,function(a,b){return a.substr(0,1)=="a"});
    alert(arr2);
    */
    filter:
    function(arr, callback, pThis) {
    var rlt = [];
    for (var i = 0, len = arr.length; i < len; i++) {
    if ((i in arr) && callback.call(pThis, arr[i], i, arr)) {
    rlt.push(arr[i]);
    }
    }
    return rlt;
    },

    /**
    * 判断数组中是否有元素满足条件。
    * @method some
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数.
    * @param {Object} pThis (Optional) 指定callback的this对象.
    * @return {boolean} 如果存在元素满足条件,则返回true.
    * @example
    var arr=["aa","ab","bc"];
    var arr2=filter(arr,function(a,b){return a.substr(0,1)=="a"});
    alert(arr2);
    */
    some:
    function(arr, callback, pThis) {
    for (var i = 0, len = arr.length; i < len; i++) {
    if (i in arr && callback.call(pThis, arr[i], i, arr)) {
    return true;
    }
    }
    return false;
    },

    /**
    * 判断数组中所有元素都满足条件。
    * @method every
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数.
    * @param {Object} pThis (Optional) 指定callback的this对象.
    * @return {boolean} 所有元素满足条件,则返回true.
    * @example
    var arr=["aa","ab","bc"];
    var arr2=filter(arr,function(a,b){return a.substr(0,1)=="a"});
    alert(arr2);
    */
    every:
    function(arr, callback, pThis) {
    for (var i = 0, len = arr.length; i < len; i++) {
    if (i in arr && !callback.call(pThis, arr[i], i, arr)) {
    return false;
    }
    }
    return true;
    },

    /**
    * 返回一个元素在数组中的位置(从前往后找)。如果数组里没有该元素,则返回-1
    * @method indexOf
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Object} obj 元素,可以是任何类型
    * @param {int} fromIdx (Optional) 从哪个位置开始找起,如果为负,则表示从length+startIdx开始找
    * @return {int} 则返回该元素在数组中的位置.
    * @example
    var arr=["a","b","c"];
    alert(indexOf(arr,"c"));
    */
    indexOf:
    function(arr, obj, fromIdx) {
    var len = arr.length;
    fromIdx
    |= 0; //取整
    if (fromIdx < 0) {
    fromIdx
    += len;
    }
    if (fromIdx < 0) {
    fromIdx
    = 0;
    }
    for (; fromIdx < len; fromIdx++) {
    if (fromIdx in arr && arr[fromIdx] === obj) {
    return fromIdx;
    }
    }
    return -1;
    },

    /**
    * 返回一个元素在数组中的位置(从后往前找)。如果数组里没有该元素,则返回-1
    * @method lastIndexOf
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Object} obj 元素,可以是任何类型
    * @param {int} fromIdx (Optional) 从哪个位置开始找起,如果为负,则表示从length+startIdx开始找
    * @return {int} 则返回该元素在数组中的位置.
    * @example
    var arr=["a","b","a"];
    alert(lastIndexOf(arr,"a"));
    */
    lastIndexOf:
    function(arr, obj, fromIdx) {
    var len = arr.length;
    fromIdx
    |= 0; //取整
    if (!fromIdx || fromIdx >= len) {
    fromIdx
    = len - 1;
    }
    if (fromIdx < 0) {
    fromIdx
    += len;
    }
    for (; fromIdx > -1; fromIdx--) {
    if (fromIdx in arr && arr[fromIdx] === obj) {
    return fromIdx;
    }
    }
    return -1;
    },

    /**
    * 判断数组是否包含某元素
    * @method contains
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Object} obj 元素,可以是任何类型
    * @return {boolean} 如果元素存在于数组,则返回true,否则返回false
    * @example
    var arr=["a","b","c"];
    alert(contains(arr,"c"));
    */
    contains:
    function(arr, obj) {
    return (ArrayH.indexOf(arr, obj) >= 0);
    },

    /**
    * 清空一个数组
    * @method clear
    * @static
    * @param {Array} arr 待处理的数组.
    * @return {void}
    */
    clear:
    function(arr) {
    arr.length
    = 0;
    },

    /**
    * 将数组里的某(些)元素移除。
    * @method remove
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Object} obj0 待移除元素
    * @param {Object} obj1 … 待移除元素
    * @return {number} 返回第一次被移除的位置。如果没有任何元素被移除,则返回-1.
    * @example
    var arr=["a","b","c"];
    remove(arr,"a","c");
    alert(arr);
    */
    remove:
    function(arr, obj) {
    var idx = -1;
    for (var i = 1; i < arguments.length; i++) {
    var oI = arguments[i];
    for (var j = 0; j < arr.length; j++) {
    if (oI === arr[j]) {
    if (idx < 0) {
    idx
    = j;
    }
    arr.splice(j
    --, 1);
    }
    }
    }
    return idx;
    },

    /**
    * 数组元素除重,得到新数据
    * @method unique
    * @static
    * @param {Array} arr 待处理的数组.
    * @return {void} 数组元素除重,得到新数据
    * @example
    var arr=["a","b","a"];
    alert(unique(arr));
    */
    unique:
    function(arr) {
    var rlt = [],
    oI
    = null,
    indexOf
    = Array.IndexOf || ArrayH.indexOf;
    for (var i = 0, len = arr.length; i < len; i++) {
    if (indexOf(rlt, oI = arr[i]) < 0) {
    rlt.push(oI);
    }
    }
    return rlt;
    },

    /**
    * 为数组元素进行递推操作。
    * @method reduce
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数。
    * @param {any} initial (Optional) 初始值,如果没有这初始,则从第一个有效元素开始。没有初始值,并且没有有效元素,会抛异常
    * @return {any} 返回递推结果.
    * @example
    var arr=[1,2,3];
    alert(reduce(arr,function(a,b){return Math.max(a,b);}));
    */
    reduce:
    function(arr, callback, initial) {
    var len = arr.length;
    var i = 0;
    if (arguments.length < 3) { //找到第一个有效元素当作初始值
    var hasV = 0;
    for (; i < len; i++) {
    if (i in arr) {
    initial
    = arr[i++];
    hasV
    = 1;
    break;
    }
    }
    if (!hasV) {throw new Error("No component to reduce"); }
    }
    for (; i < len; i++) {
    if (i in arr) {
    initial
    = callback(initial, arr[i], i, arr);
    }
    }
    return initial;
    },

    /**
    * 为数组元素进行逆向递推操作。
    * @method reduceRight
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Function} callback 需要执行的函数。
    * @param {any} initial (Optional) 初始值,如果没有这初始,则从第一个有效元素开始。没有初始值,并且没有有效元素,会抛异常
    * @return {any} 返回递推结果.
    * @example
    var arr=[1,2,3];
    alert(reduceRight(arr,function(a,b){return Math.max(a,b);}));
    */
    reduceRight:
    function(arr, callback, initial) {
    var len = arr.length;
    var i = len - 1;
    if (arguments.length < 3) { //逆向找到第一个有效元素当作初始值
    var hasV = 0;
    for (; i > -1; i--) {
    if (i in arr) {
    initial
    = arr[i--];
    hasV
    = 1;
    break;
    }
    }
    if (!hasV) {
    throw new Error("No component to reduceRight");
    }
    }
    for (; i > -1; i--) {
    if (i in arr) {
    initial
    = callback(initial, arr[i], i, arr);
    }
    }
    return initial;
    },

    /**
    * 将一个数组扁平化
    * @method expand
    * @static
    * @param arr {Array} 要扁平化的数组
    * @return {Array} 扁平化后的数组
    */
    expand:
    function(arr) {
    return [].concat.apply([], arr);
    },

    /**
    * 将一个泛Array转化成一个Array对象。
    * @method toArray
    * @static
    * @param {Array} arr 待处理的Array的泛型对象.
    * @return {Array}
    */
    toArray:
    function(arr) {
    var ret = [];
    for (var i = 0; i < arr.length; i++) {
    ret[i]
    = arr[i];
    }
    return ret;
    },


    /**
    * 对数组进行包装。
    * @method wrap
    * @static
    * @param {Array} arr 待处理的数组.
    * @param {Class} constructor 构造器
    * @returns {Object}: 返回new constructor(arr)
    */
    wrap:
    function(arr, constructor) {
    return new constructor(arr);
    }
    };

    QW.ArrayH
    = ArrayH;

    }());

    function.h.js (针对Function的Helper)
    View Code
    /**
    * @class FunctionH 核心对象Function的扩展
    * @singleton
    * @namespace QW
    * @helper
    */
    (
    function() {

    var FunctionH = {
    /**
    * 函数包装器 methodize,对函数进行methodize化,使其的第一个参数为this,或this[attr]。
    * @method methodize
    * @static
    * @param {function} func要方法化的函数
    * @param {string} attr (Optional) 属性
    * @return {function} 已方法化的函数
    */
    methodize:
    function(func, attr) {
    if (attr) {
    return function() {
    return func.apply(null, [this[attr]].concat([].slice.call(arguments)));
    };
    }
    return function() {
    return func.apply(null, [this].concat([].slice.call(arguments)));
    };
    },
    /** 对函数进行集化,使其第一个参数可以是数组
    * @method mul
    * @static
    * @param {function} func
    * @param {bite} opt 操作配置项,缺省表示默认,
    1 表示getFirst将只操作第一个元素,
    2 表示joinLists,如果第一个参数是数组,将操作的结果扁平化返回
    * @return {Object} 已集化的函数
    */
    mul:
    function(func, opt) {
    var getFirst = opt == 1,
    joinLists
    = opt == 2;

    if (getFirst) {
    return function() {
    var list = arguments[0];
    if (!(list instanceof Array)) {
    return func.apply(this, arguments);
    }
    if (list.length) {
    var args = [].slice.call(arguments, 0);
    args[
    0] = list[0];
    return func.apply(this, args);
    }
    };
    }

    return function() {
    var list = arguments[0];
    if (list instanceof Array) {
    var moreArgs = [].slice.call(arguments, 0),
    ret
    = [],
    i
    = 0,
    len
    = list.length,
    r;
    for (; i < len; i++) {
    moreArgs[
    0] = list[i];
    r
    = func.apply(this, moreArgs);
    if (joinLists) {
    if (r) {
    ret
    = ret.concat(r);
    }
    }
    else {
    ret.push(r);
    }
    }
    return ret;
    }
    else {
    return func.apply(this, arguments);
    }
    };
    },
    /**
    * 函数包装变换
    * @method rwrap
    * @static
    * @param {func}
    * @return {Function}
    */
    rwrap:
    function(func, wrapper, idx) {
    idx
    |= 0;
    return function() {
    var ret = func.apply(this, arguments);
    if (idx >= 0) {
    ret
    = arguments[idx];
    }
    return wrapper ? new wrapper(ret) : ret;
    };
    },
    /**
    * 绑定
    * @method bind
    * @via https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
    * @compatibile ECMA-262, 5th (JavaScript 1.8.5)
    * @static
    * @param {func} 要绑定的函数
    * @obj {object} this_obj
    * @param {any} arg1 (Optional) 预先确定的参数
    * @param {any} arg2 (Optional) 预先确定的参数
    * @return {Function}
    */
    bind:
    function(func, obj) {
    var slice = [].slice,
    args
    = slice.call(arguments, 2),
    nop
    = function() {},
    bound
    = function() {
    return func.apply(this instanceof nop ? this : (obj || {}), args.concat(slice.call(arguments)));
    };

    nop.prototype
    = func.prototype;

    bound.prototype
    = new nop();

    return bound;
    },
    /**
    * 懒惰执行某函数:一直到不得不执行的时候才执行。
    * @method lazyApply
    * @static
    * @param {Function} fun 调用函数
    * @param {Object} thisObj 相当于apply方法的thisObj参数
    * @param {Array} argArray 相当于apply方法的argArray参数
    * @param {int} ims interval毫秒数,即window.setInterval的第二个参数.
    * @param {Function} checker 定期运行的判断函数。<br/>
    对于不同的返回值,得到不同的结果:<br/>
    返回true或1,表示需要立即执行<br/>
    返回-1,表示成功偷懒,不用再执行<br/>
    返回其它值,表示暂时不执行<br/>
    * @return {int} 返回interval的timerId
    */
    lazyApply:
    function(fun, thisObj, argArray, ims, checker) {
    checker
    = checker || function() {return true; };
    var timer = function() {
    var verdict = checker();
    if (verdict == 1) {
    fun.apply(thisObj, argArray
    || []);
    }
    if (verdict == 1 || verdict == -1) {
    clearInterval(timerId);
    }
    },
    timerId
    = setInterval(timer, ims);
    return timerId;
    }
    };


    QW.FunctionH
    = FunctionH;

    }());


  • 相关阅读:
    本地快速搭建 FTP 服务器
    css 四个角
    时间
    两个json深度对比
    工作常用
    js模块化 中的变量可在局部 中的‘全局共享’
    datatables 的导出button自定义
    css布局技巧
    datables自定义排序
    js判断是否为空 或者全部为空
  • 原文地址:https://www.cnblogs.com/jkisjk/p/qwrap_helper.html
Copyright © 2020-2023  润新知