有跟贴分享的童鞋一律有分,大家也发一发自己平时用的小东东呀。
PS:代码太长发不了,只好这样了.点击美化
(function(){utils={proxy:function(){this.string.proxy();this.date.proxy();this.cookie.proxy();this.dataType2.proxy();window.dataType=this.dataType},dataType:{get:function(a){return Object.prototype.toString.call(a).match(/^\[object\s(.*)\]$/)[1]},is:function(a,b){return b.split(',').length>1?b.toLowerCase().indexOf(this.get(a).toLowerCase())>-1:this.get(a).toLowerCase()==b.toLowerCase()}},dataType2:{get:function(){return Object.prototype.toString.call(this).match(/^\[object\s(.*)\]$/)[1]},is:function(a){return a.split(',').length>0?a.toLowerCase().indexOf(this.getType().toLowerCase())>-1:this.getType().toLowerCase()==a.toLowerCase()},proxy:function(){Object.prototype.isType=this.is;Object.prototype.getType=this.get}},string:{byteLength:function(){if(this.isEmpty()){return 0};var match=this.match(/[^\x00-\x80]/g);return(this.length+(!match?0:match.length))},cut:function(a,b,c){if(this.isEmpty()){return this}var d=this,e=0,f='',g=b?d.byteLength():d.length,h=(c?(g>a?c:''):'');if(a>=g){return this};for(i=0;i<d.length;i++){if(b){e+=(d.charCodeAt(i)>255)?2:1;f+=d.charAt(i);if(e>=a){return f+h}}else{if(i>=a){return f+h}f+=d.charAt(i)}};return d+h},trim:function(){return this.replace(/(^\s*)|(\s*$)/g,"")},isEmpty:function(){return this.trim().length==0},format:function(){var args=arguments;return this.replace(/\{(\d+)\}/g,function(m,i){return args[i]})},toFloat:function(a,b){a=dataType.is(a,'number')?a:!1,b=dataType.is(b,'boolean')?b:!0;try{var c=a?(b?(this*1).toFixed(a)*1:this.toString().replace(new RegExp("([0-9]+\.[0-9]{"+a+"})[0-9]*","g"),"$1")*1):(this*1);return isNaN(c)?this:c}catch(e){return this*1}},toDate:function(){var a=this,b={"-":!0,"年":!0,"月":!0,"日":!1,"时":!0,"分":!0,"秒":!1};if(dataType.is(a,'string')){for(var i in b){a=a.replace(i,b[i]?'/':'')};var c=new Date(Date.parse(a));if(isNaN(c)){throw new Error('源数据['+this+']无法转化为日期格式');return this};return c}else{return new Date(a)}},proxy:function(){String.prototype.format=this.format;String.prototype.toFloat=Number.prototype.toFloat=this.toFloat;String.prototype.toDate=Number.prototype.toDate=this.toDate;String.prototype.byteLength=this.byteLength;String.prototype.cut=this.cut;String.prototype.trim=this.trim;String.prototype.isEmpty=this.isEmpty}},date:{format:function(b){var a=this,o={"M+":a.getMonth()+1,"d+":a.getDate(),"h+":a.getHours(),"m+":a.getMinutes(),"s+":a.getSeconds(),"W":["日","一","二","三","四","五","六"][a.getDay()],"q+":Math.floor((a.getMonth()+3)/3),"S":a.getMilliseconds()};if(/(y+)/.test(b)){b=b.replace(RegExp.$1,(a.getFullYear()+"").substr(4-RegExp.$1.length))};for(var k in o){if(new RegExp("("+k+")").test(b)){b=b.replace(RegExp.$1,RegExp.$1.length==1?o[k]:("00"+o[k]).substr((""+o[k]).length))}};return b},add:function(a){if(a.length==0){return this}var b=this,c=a.match(/((-\d+)+|(\d+))/g),d=a.match(/y+|M+|d+|h+|m+|s+/g),e={'y':function(f){return b.setFullYear(b.getFullYear()+f*1)},'M':function(f){return b.setMonth(b.getMonth()+f*1)},'d':function(f){return b.setDate(b.getDate()+f*1)},'h':function(f){return b.setHours(b.getHours()+f*1)},'m':function(f){return b.setMinutes(b.getMinutes()+f*1)},'s':function(f){return b.setSeconds(b.getSeconds()+f*1)}};for(var i=0;i<c.length;i++){e[d[i].substr(0,1)](c[i]).toDate()};return b},proxy:function(){Date.prototype.format=this.format;Date.prototype.add=this.add}},cookie:{set:function(a){if(dataType.is(a,'string,number')){a={value:a}}else if(!a){return};var time=a.time?'; expis='+new Date().add(a.time).toGMTString():'',path=a.path?'; path='+a.path:'',domain=a.domain?'; domain='+a.domain:'',secure=a.secure?'; secure':'',value=a.value?encodeURIComponent(a.value):'';document.cookie=[this,'=',value,time,path,domain,secure].join('')},get:function(){if(!document.cookie||(document.cookie&&document.cookie=='')){return''};var a=document.cookie.split(";");for(var i=0;i<a.length;i++){var arr=a[i].split("=");if(arr[0].trim()==this.trim()){var b=decodeURIComponent(arr[1]);return b=='undefined'?'':b}};return''},del:function(){if(this.isEmpty()){this.delAllCookie()}else{this.setCookie({time:'-1s'})}},delAll:function(){var keys=document.cookie.match(/[^ =;]+(?=\=)/g);if(keys){for(var i=0;i<keys.length;i++){keys[i].setCookie({time:'-1s'})}}},proxy:function(){String.prototype.getCookie=this.get;String.prototype.setCookie=this.set;String.prototype.delCookie=this.del;String.prototype.delAllCookie=this.delAll}}};utils.proxy()})();

解决方案 »

  1.   

    使用说明:
    /// <summary>
    /// String,Number原型扩展:保留指定的小数位数[可选择是否使用四舍五入]
    /// </summary>
    /// <param name="a">需要保留的小数位</param>
    /// <param name="b">是否是舍五入[可选项:默认true]</param>
    /// <returns>数据类型:Number(浮点数)</returns>
    四舍五入:    (2.35555).toFloat(3)=2.356
    非四舍五入:  (2.35555).toFloat(3,!1)=2.355
    简单容错:    (2.35555).toFloat(!0)=2.35555四舍五入:    "2.35555".toFloat(3)=2.356
    非四舍五入:  "2.35555".toFloat(3,!1)=2.355
    简单容错:    "2.35555".toFloat(!0)=2.35555/// <summary>
    /// String原型扩展:去除左右空格
    /// </summary>
    /// <returns>数据类型:String</returns>
    调用方式:'aaaa中  '.trim()='aaaa中'/// <summary>
    /// String原型扩展:按字节取长度,汉字计为两字节
    /// </summary>
    /// <returns>字符串总长度</returns>
    调用方式:'aaaa中'.byteLength()=6/// <summary>
    /// String原型扩展:字符串等效项替换[string.Format()伪实现]
    /// </summary>
    /// <param name="arguments">arguments数组</param>
    /// <returns>替换后的字符串</returns>
    调用方式:"a{0}b{1}c{2}".format("x","y","z")="axbycz"/// <summary>
    /// String原型扩展:是否空字符串
    /// </summary>
    /// <returns>Boolean</returns>
    调用方式:"".isEmpty()=true
    调用方式:"a".isEmpty()=false/// <summary>
    /// String原型扩展:截取指定长度的字符串
    /// </summary>
    /// <param name="a">要截取的长度</param>
    /// <param name="b">是否将汉字计为2个长度:true|false</param>
    /// <param name="c">截取的长度小于原字符串的总长度时,附加的文本,比如:...</param>
    /// <returns>截取后的字符串</returns>
    调用方式:"1中中2345".cut(3)="1中中"
    调用方式:"1中中2345".cut(3,true)="1中"
    调用方式:"1中中2345".cut(3,false)="1中中"
    调用方式:"1中中2345".cut(3,true,"...")="1中..."
    调用方式:"1中中2345".cut(3,false,"...")="1中中..."
    调用方式:"1中中2345".cut(9,true,"...")="1中中2345"
    调用方式:"1中中2345".cut(7,false,"...")="1中中2345"/// <summary>
    /// String,Number原型扩展:转换为日期格式[函数中定义了一个常规的替换项模板,有特殊使用时可进行修改]
    /// </summary>
    /// <returns>数据类型:Date</returns>
    调用方式:1:Number:(1000*60*60*24).toDate()=Fri Jan 2 08:00:00 UTC+0800 1970
    调用方式:2:String:"2012年10月27日 11:56:12".toDate()=Sat Oct 27 11:56:12 UTC+0800 2012/// <summary>
    /// Date原型扩展:日期运算
    /// 参数格式:yMdhms分别表示[年月日时分秒,前面使用正负数字表示做加运算还是减运算]1y=加1年,1M=加1个月,1d=加1天,1h=加1个小时,1m=加1分钟,1s=加1秒钟
    /// </summary>
    /// <param name="a">加减日期{参数格式:参考上面的说明}</param>
    /// <returns>数据类型:Date</returns>
    调用方式:new Date().add('1y1M1d1h1m1s')=Sat Nov 30 00:07:16 UTC+0800 2013/// <summary>
    /// Date原型扩展:日期格式化
    /// </summary>
    /// <param name="a">格式化模板[yMdhms:分别表示-年月日时分秒,q="季度",W="星期"]</param>
    /// <returns>数据类型:String</returns>
    调用方式:new Date().format('yyyy-MM-dd 第q季度 星期W hh:mm:ss')=2012-10-28 第4季度 星期日 23:06:15/// <summary>
    /// 复合使用示例
    /// </summary>
    调用方式:1:Number:(1000*60*60*24).toDate().add('1y1M1d1h1m1s').format('yyyy-MM-dd 第q季度 星期W hh:mm:ss')=1971-02-03 第1季度 星期三 09:01:01
    调用方式:2:String:"2012年10月27日 11:56:12".toDate().add("1y1M1d1h1m1s").format("yyyy-MM-dd 第q季度 星期W hh:mm:ss")=2013-11-28 第4季度 星期四 12:57:13/// <summary>
    /// String原型扩展:设置cookie
    /// </summary>
    /// <param name="a">完整格式:{value:值,time:有效日期[与日期运算中的参数格式一致],path:访问目录,domain:域,secure:安全性}</param>
    /// <returns>以调用对象作为cookie的键名设置cookie</returns>
    最简调用:"test".setCookie(1||"1");//设置cookie:test=1,有效日期:关闭浏览器后立刻失效
    字面量传参:"test".setCookie({value:2,time:"1y"});//设置cookie:test=2,有效日期:1年/// <summary>
    /// String原型扩展:获取cookie
    /// </summary>
    /// <returns>以调用对象作为cookie的键名获取它的cookie值,不存在时返回空字符串</returns>
    调用方式:"test".getCookie();//获取名称为test的cookie值/// <summary>
    /// String原型扩展:删除cookie
    /// </summary>
    /// <returns>以调用对象作为cookie的键名删除它的cookie,当调用对象是空字符串时可清除所有cookie</returns>
    调用方式:"test".delCookie();//删除键名为test的cookie
    调用方式:"".delCookie();//删除所有cookie
      

  2.   

    ///格式日期
     Date.prototype.format = function(format)
     {
         var o ={
                "M+" : this.getMonth()+1, //month
                "d+" : this.getDate(),    //day
                "h+" : this.getHours(),   //hour
                "s+" : this.getSeconds(), //second
                "m+" : this.getMinutes(), //minute
                "q+" : Math.floor((this.getMonth()+3)/3),  //quarter 
                "S" : this.getMilliseconds() //millisecond     
            }
           if(/(y+)/.test(format))
                 format=format.replace(RegExp.$1,(this.getFullYear()+"").substr(4 - RegExp.$1.length));
          for(var k in o)     
                 if(new RegExp("("+ k +")").test(format))
             format = format.replace(RegExp.$1,RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length));
             return format; 
     };
    String.prototype.Trim=function(){
        return this.replace(/(^\s*)|(\s*$)/g,'');
    };
    Array.prototype.contain=function(value){
        if(this!=null && this.length>0){
            for(var i=0;i<this.length;i++)
            {
                if(this[i]==value){
                    return true;
                }
            }
        }
        return false;
    };
      Array.prototype.indexOf = function(val) {
                for (var i = 0; i < this.length; i++) {
                    if (this[i] == val) return i;
                }
                return -1;
            };
    Array.prototype.remove = function(val) {
                var index = this.indexOf(val);
                if (index > -1) {
                    this.splice(index, 1);
                }
            };//获取上一个节点
    function getPreviousChild(obj) { 
        var result = obj.previousSibling; 
        while (!result.tagName) { 
             result = result.previousSibling; 
        } 
        return result; 
    }
    //获取下一个节点
    function getNextChild(obj) { 
        var result = obj.nextSibling; 
        while (!result.tagName) { 
             result = result.nextSibling; 
        } 
        return result; 
    } /********************
     * 取窗口滚动条滚动高度 
     ******************/
     function getScrollTop()
    {
       return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop ;
    };
    /********************
     * 取窗口可视范围的高度 
     *******************/
     function  getClientHeight()
    {
         return (navigator.userAgent.toLowerCase().indexOf('opera') != -1)?document.body.clientHeight:document.documentElement.clientHeight;         
    };
    /********************
     * 取窗口可视范围的宽度 
     *******************/
     function  getClientWidth()

       return (navigator.userAgent.toLowerCase().indexOf('opera') != -1)?document.body.clientWidth:document.documentElement.clientWidth;  
    };
     // 动态导入js
    function include(src,encoding,fun) 

        var s = $C('script');   
        s.type='text/javascript';
        s.charset=encoding; //'gb2312';
        s.src = src;   
        var tags =$$('head');   
       if(typeof(fun)=='function'){
            if( document.all ){
               s.onreadystatechange = function(){
                    if(/(complete|loaded)/.test(this.readyState)){
                          fun(); s.onreadystatechange = null; s.parentNode.removeChild(s); 
                     }};
           }else{
                 s.onload = function(){  fun(); s.onload = null; s.parentNode.removeChild(s); };
           }
        } 
        tags[0].appendChild(s); 
    };
        
    // 绑定事件
    function bindEvent(obj,evt,fun) 
    {
         if(window.addEventListener){
               obj.addEventListener(evt, function(e){ fun(e);},false); 
         }else{
               obj.attachEvent('on'+evt,fun);     
        }
    } function getAbsPoint(e)
    {
        var x = e.offsetLeft;
        var y = e.offsetTop;
        while(e = e.offsetParent)
        {
            x += e.offsetLeft;
            y += e.offsetTop;
        }
        return {'x': x, 'y': y};
    };
      

  3.   

    可算是引出一个来了
    正在导入自己的。
    Array.prototype.contain与Array.prototype.indexOf功能性重复
      

  4.   

    嗯。这种事情以前讨论过。一般的经验是:“绝对不要扩展内置类型的原型,除非是为了和新的 JavaScript 引擎兼容”。即使必须扩展,我认为给公开成员和方法起中文名也更好一点,起码在必须使用所造成的问题中减少一个问题。
      

  5.   

    因为你既然想作为工具提供出来供人使用,那在传播使用过程中,会出现很多在你看不该出现的问题:1.首先是对新手来说,如果没有看到扩展声明,只是看到直接调用的代码,就会把你的扩展和内置对象方法搞混,以为原来就有或者原来就是这样的处理方式。对有一点基础的新手,又会引起困惑,不知怎么和所学过的不一样了。2.当代码被部分复制时,如果你使用自己组织的类库,就很容易让人从函数调用的格式上知道这是你的类库方法,并连同你的类库一同复制才能生效。如果使用扩展,尤其是通过重载原型方法进行的功能扩展,很难让人注意到这一点,就会导致复制后的代码不能运行或者结果与原来不同(尤其是后种,更不好排查)。
      这一点,与“除非是为了和新的 JavaScript 引擎兼容”的原则所产生的效果正好相反。如果按照那个原则,只在低版本引擎中扩展原型,那么就可以无需连同复制定义扩展的JS,直接把使用代码复制到高版本引擎中使用即可,因为高版本正好支持了那些功能。否则就不行了。3.一旦不禁止使用这种方法,那么各种对原型的扩展就会存在,到时可能除了你的扩展,还同时有别人的JS库里含有对同样方法的扩展,而实现的目标可能有差异,这样无论是你重载了他,还是他重载了你,都会很混乱。合并多个对原型有相同覆盖部分的扩展时,也会比较麻烦,更不用说在取舍时是否还要比较实现方法的好坏。而如果使用类库形式,则只要想调用哪个库的哪个方法就调用哪个,不需要的不调用即可。4.扩展原型必然会改变原型结构。在其它地方如果涉及到对原型结构进行遍历操作,或者是针对原来的结构与方法进行的特定操作时,可能与其针对原结构而设计的预期冲突而造成该部分的功能异常或者出错。比如我曾举例过的改变ARRAY的LENGTH后,所有新声明的数组都不能再通过LENGTH进行FOR遍历,虽然这是比较极端和不普遍的修改,但其它修改也会造成类似现象,隐患始终存在,只看诱因是否出现,而你不能保证别人一定不会使用与之可能冲突的代码,甚至你也想不到所有也许会冲突的可能性。所有BUG都是因为在我们意料之外的使用情况,意料之内的我们自然已经解决了。概括的话,扩展原型和建立类库是效果截然相反的两种代码组织方法。扩展原型不利于代码的组织、使用、管理,甚至是理解,而且容易与其它没有考虑到你这些扩展或重载的代码产生差异性错误或不同结果,又或者是因为相同的重载而产生覆盖冲突。实际所衍生的问题就多了。
      

  6.   

    1,2两点倒还好说了,偏重于使用前的理解问题3,4两点就比较严重了
    就像是我如果要对Object原型进行扩展时一样。jQuery这么成熟的框架,居然也没有在for in中使用hasOwnProperty()来过滤原型扩展。看来不是人家粗心,是这种方式确实在应用中应该被避免为佳要是我自己用的话倒是没什么问题,这么提供出来确实是有点欠考虑了。之所以使用原型扩展的方式,我只是想使得调用更直接,其实在上传这些代码之前,所有的代码都是兼容类库方式调用和基于对象原型方式调用的。只是因为参数的处理部份多了些,所以被我全部去除了。只保留了基于对象原型方式调用
    改成类库方式也简单就是。加多个参数替换this倒也方便
      

  7.   


    想先考虑一下调用方式的问题。
    Object的原型扩展这个是直接放弃了
    数组呢也很重要,对其直接进行原型扩展也是很容易出现错误的,虽然我本人不用for in遍历,但架不住别人已经用过的。所以我发出的代码里并没有对数组的原型扩展,就是基于这个原因被我先抠掉了Date我觉得还是直接使用原型扩展就可以了
    String嘛,有打算保留目前这种原型扩展的方式,但也有想过使用静态方法调用:String.trim(字符串)
    Array嘛,这个是打算使用静态方法调用了:Array.each(arr,fn)给点意见参考下吧
      

  8.   

    扩展原型
    不如直接写自己的 工具类 更实用至少我用的时候 知道是怎么回事
    而且代码的兼容性更好Array.each ==>  utils.each
      

  9.   


    先谢谢提供建议
    使用Array.each这种静态方法调用,包括这些原型的扩展,其实都是出于一个相同的目的。调用简便你也应该看得出来,在写的时候,我是将对应的方法归到其所属的数据类型下面的如果这样使用:utils.each(arr,fn),
    那我感觉还不如:utils.array.each(arr,fn),虽然长了点,但对方法的归属却更清晰
    其他的还好说。只是在数组上可供使用的方法太多。添加,复制,合并,排重,交集,索引,过滤等等,加起来二十来种都怕是有了。所以才会使用这种伪命名空间的方式将每个方法归到对应的数据类型下面。阅读起来也更方便
    主要是我写的时候就是这么一个一个写下来的。感觉结构更清晰点
      

  10.   

    也来一个,这个是自己以前经常用的一个字符串处理小工具
    'use strict';var StrUtil = (function(){var Cache = {};var FmtHelper = {
     
      /**
      * 执行用户自定义函数. 
      * @param  {String}param     函数名称
      * @param  {String}propName  属性名称
      * @param  {String}propVal   属性值
      * @param  {JSON}context
      * @return {String} 
      *@example
      *  var params = {
      *    name   : 'zhang-san',
      *    gender : 'male'
      *  }
      *  
      *  var temp = (
      *    "hello #{name} #{gender, $exec(getTitle)}!"
      *  );
      *
      *  var output = StrUtil.simpleFormat(temp, params, {
      *    getTitle : function(key, val, context){
      *      console.log(context);
      *      return val == 'male' ? '先生' : '小姐';
      *    }
      *  });
      *
      *  console.log(output);
      */  
      exec : function(param, propName, propVal, context){
        var ret = null, handler;
        param   = param.replace(/^\s+/g,'').replace(/\s+$/g, '');
        handler = context.handlers && context.handlers[param];
        
        if(handler instanceof Function){
          ret = handler(propName, propVal, context);
        }
        
        return ret;
      },
      
      map : function(mapData, propName, propVal, context){
        var handleStr = function(str){
          if(!str) { return "" }
          
          var firstChar = str.charAt(0);
          if(firstChar == "'" || firstChar == "\""){
            return str.substring(1, str.length - 1);      
          }
          
          return str;    
        }
        
        var map = (function(){
          if( Cache[mapData] ){
            return Cache[mapData];
          }      var reg = /([^,'":\s]+|'.*?'|".*?")\s*:\s*([^,'":\s]+|'.*?'|".*?")/g;
          var m, k, v, newMap = {};
          while(m = reg.exec(mapData)){
            k = handleStr(m[1]);
            v = handleStr(m[2]);        
            if(k && v){
              newMap[k] = v;
            }
          }      
          
          Cache[mapData] = newMap;
          return newMap;
        })();
        
        return map[propVal] || map['else'] || '';
      },
      
      /**
      * 当参数超过指定长度时截取并显示省略号。
      * 可按长度和宽度进行截取。
      * @param  {String}param   参数设置字符串
      * @param  {String}propVal 属性值
      * @return {String}  
      * @example 
      *
      *   var t1 = "Hello #{0->$sub(5,l)}!";          //默认按长度截取,l可省略
      *   var t2 = "Hello #{0->$sub(5,w)}!";
      *   var t3 = "Hello #{0->$sub(5,w,>>>)}!"
      *   
      *  1.按长度截取
      *   StrUtil.simpleFormat(t1, "ABCDEFG");        //Hello AB...!
      *   StrUtil.simpleFormat(t1, "星期六的黄昏");   //Hello 星期...!
      *  
      *  2.按宽度截取
      *  StrUtil.simpleFormat(t2, "ABCDEFGHIJKLM");  //Hello ABCDEF...!
      *  StrUtil.simpleFormat(t2, "星期六的黄昏");   //Hello 星期六...!
      *  
      *  3.定义省略号
      *  StrUtil.simpleFormat(t3, "ABCDEFGHIJKLM");  //Hello ABCDEF>>>!
      *  StrUtil.simpleFormat(t3, "星期六的黄昏");   //Hello 星期六>>>! 
      */
      sub : function(param, propName, propVal, context){
        var args = param.replace(/\s+/g, '').split(',');
        var max  = parseInt(args[0]);
        var mask = args[2] || "...";
        var byWidth = args.length > 1 && args[1] == "w";
        var maskLen, propLen;
        
        if(byWidth){
          maskLen = StrUtil.getStrWidth(mask);
          propLen = StrUtil.getStrWidth(propVal);
        }else{
          maskLen = mask.length;
          propLen = propVal.length;
        }
        
        if(propLen <= max){
          return propVal;
        }     if(maskLen >= max){
          return mask;
        }    
          
        return (
            byWidth
          ? StrUtil.cutStrByWidth(propVal, max - maskLen) + mask
          : propVal.substring(0, max - maskLen) + mask
        );
      }
    }var StrUtil = {
      /**
      * 获取字符串宽度(英文为一个宽度,中文两个).
      * @param  {String}str
      * @return {int}
      * @public
      */
      getStrWidth : function(str){
        if(!str){ return 0; }
       
        var i, c, ret = 0, len = str.length;
        for(i=0; i<len; i++){
          c = str.charCodeAt(i);
          ret += (c > 256 ? 2 : 1); 
        }
        
        return ret;
      },  /**
      * 根据其实位置和宽度截取字符串.
      * @param {String}str
      * @param {int}width
      * @param {int}[start]  截取开始位置, 默认为0
      */
      cutStrByWidth : function(str, width, start){
        if(!str || width <= 0) { return ''; }
        
        var i, len, code, end, size = 0, ret = [];
        
        start = start == undefined ? 0 
              : start < 0 ? str.length + start
              : start; 
        end = start + width;
        
        for(i=0, len=str.length; i<len; i++){
          code  = str.charCodeAt(i);
          size += (code > 256 ? 2 : 1);
          if(size >= start && size <= end){
            ret.push(str.charAt(i));
            if(size == end){ break; }
          }      
        }
        
        return ret.join('');  
      },  /**
      * 根据膜拜进行简单格式化.
      * @param  {String}temp
      * @param  {JSON|Object|...}args
      * @param  {JSON<String, Function>}[handlers]
      * @return {String}
      * @public
      * @example
      * var t  = "welcom #{0} #{1->map(f:小姐, else:先生)}";
      * var t1 = "welcom #{name} #{gender->map(f:小姐, else:先生)}";
      * var t2 = "全文 : #{message}\n"
      *        + "概要 : #{message->sub(12,w,...)}";         
      *
      * alert(StrUtil.simpleFormat(t, "王建波", 29));
      * alert(StrUtil.simpleFormat(t1, {name   : "王建波", age: 29 }));
      * alert(StrUtil.simpleFormat(t2, {message: "123456789ABCDEFG"}));  
      */ 
      simpleFormat : function(temp, args, handlers){
        var argc = arguments.length;
        if ( arguments.length == 1 ) { return temp }
        if ( arguments.length >  3 || typeof arguments[1] != "object" ) {
          args = [].slice.call(arguments, 1, argc);
          handlers = arguments[argc -1];
        }
            
        var reg = new RegExp((
            "\\\\#\\{|#\\{"        //匹配变量转义符\#{或变量开始#{
          +   "(\\w+)"             //属性名称
          +   "(?:->\\s*"          //属性后可选的内置方法调用比如:#{name->sub(5)}
          +     "(\\w+)\\s*\\("    //内置方法名称
          +       "("              //内置方法参数
          +          "(?:[^)}\"'\\n]*?|\".*?\"|'.*?')*"
          +       ")"
          +     "\\)"             
          +   ")?"                
          + "\\}"
        ), "gi");
        
        var valCache = {};    
        
        var context = {
          handlers : handlers,
          valCache : valCache
        };
        
        var replaceHandler = function(m, prop, fn, fnParam){
          var propVal, fnRet, ret;
          
          //对于转义符,直接返回"\"之后内容
          if( m == "\\#{" ) { return "#{" }
          
          //若已经计算过直接返回
          if(valCache.hasOwnProperty(m)){
            return valCache[m];
          }      
          
          if(prop) {          
            propVal = args[prop] != undefined 
                    ? String(args[prop]) 
                    : "";
            
            //若需要对返回值进行函数调用,返回函数调用结果
            if(fn && FmtHelper.hasOwnProperty(fn)){
              try{
                fnRet = FmtHelper[fn](
                  fnParam, 
                  prop, 
                  propVal, 
                  context
                );
              }catch(e){}
            }        ret = (fnRet == undefined || fnRet == null) ? propVal : fnRet;
          }else{
            ret = m;
          }
          
          valCache[m] = ret;      
          return ret;
        };       
        
        return temp.replace(reg, replaceHandler);  
      }
    }return StrUtil;
    })();
    window.onload = function(){
      alert(StrUtil.simpleFormat(
        "hello #{0}, #{1}!",
        "张三",
        "先生"
      ));
      
      alert(StrUtil.simpleFormat(
        "hello #{name}, #{title}!",
        {name : "张三", title : "先生"}
      ));  
      
      var params = {
        id : 'user-1',
        name   : '张三',
        gender : 'male',
        pic    : 'http://www.baidu.com/img/baidu_sylogo1.gif',
        details: (
            "主要是我还从没有系统的学过js,理论方面自<br/>"
          + "己对很多东西的理解很浅显。因为不想说提供<br/>"
          + "了些东东出来结果造成使用者的意料之外的错<br/>"
          + "误或降低性能和效率。也包括使用时的体验等等"
        )
      }  var temp = (
          "hello #{name} #{gender->map(female:小姐, else:先生)}<hr/>"
        + "<pre>"
        +  " id     : #{id}<br/>"
        +  " name   : #{name}<br/>"
        +  " gender : #{gender->map(female:女, else:男)}<br/>"
        +  " pic    : <img src='#{pic}' align='top'/><br/>"
        +  " summary: #{details->sub(20, l, >>>)}<br/>"
        +  " details: #{details}"
        + "</pre>"
      );  var output = StrUtil.simpleFormat(temp, params, {
        getWelcome : function(key, val){
          return "hello " + val + ' current time is :' + new Date();
        }
      });  document.getElementById('div1').innerHTML = output;
    };
      

  11.   

    晕,注释中的例子有Bug,后来自己改了一些语法,注释没跟上。
    'use strict';var StrUtil = (function(){var Cache = {};var FmtHelper = {
     
      /**
      * 执行用户自定义函数. 
      * @param  {String}param     函数名称
      * @param  {String}propName  属性名称
      * @param  {String}propVal   属性值
      * @param  {JSON}context
      * @return {String} 
      *@example
      *  var params = {
      *    name   : 'zhang-san',
      *    gender : 'male'
      *  }
      *  
      *  var temp = (
      *    "hello #{name} #{gender->exec(getTitle)}!"
      *  );
      *
      *  var output = StrUtil.simpleFormat(temp, params, {
      *    getTitle : function(key, val, context){
      *      console.log(context);
      *      return val == 'male' ? '先生' : '小姐';
      *    }
      *  });
      *
      *  console.log(output);
      */  
      exec : function(param, propName, propVal, context){
        var ret = null, handler;
        param   = param.replace(/^\s+/g,'').replace(/\s+$/g, '');
        handler = context.handlers && context.handlers[param];
        
        if(handler instanceof Function){
          ret = handler(propName, propVal, context);
        }
        
        return ret;
      },
      
      map : function(mapData, propName, propVal, context){
        var handleStr = function(str){
          if(!str) { return "" }
          
          var firstChar = str.charAt(0);
          if(firstChar == "'" || firstChar == "\""){
            return str.substring(1, str.length - 1);      
          }
          
          return str;    
        }
        
        var map = (function(){
          if( Cache[mapData] ){
            return Cache[mapData];
          }      var reg = /([^,'":\s]+|'.*?'|".*?")\s*:\s*([^,'":\s]+|'.*?'|".*?")/g;
          var m, k, v, newMap = {};
          while(m = reg.exec(mapData)){
            k = handleStr(m[1]);
            v = handleStr(m[2]);        
            if(k && v){
              newMap[k] = v;
            }
          }      
          
          Cache[mapData] = newMap;
          return newMap;
        })();
        
        return map[propVal] || map['else'] || '';
      },
      
      /**
      * 当参数超过指定长度时截取并显示省略号。
      * 可按长度和宽度进行截取。
      * @param  {String}param   参数设置字符串
      * @param  {String}propVal 属性值
      * @return {String}  
      * @example 
      *
      *   var t1 = "Hello #{0->sub(5,l)}!";          //默认按长度截取,l可省略
      *   var t2 = "Hello #{0->sub(5,w)}!";
      *   var t3 = "Hello #{0->sub(5,w,>>>)}!"
      *   
      *  1.按长度截取
      *   StrUtil.simpleFormat(t1, "ABCDEFG");        //Hello AB...!
      *   StrUtil.simpleFormat(t1, "星期六的黄昏");   //Hello 星期...!
      *  
      *  2.按宽度截取
      *  StrUtil.simpleFormat(t2, "ABCDEFGHIJKLM");  //Hello ABCDEF...!
      *  StrUtil.simpleFormat(t2, "星期六的黄昏");   //Hello 星期六...!
      *  
      *  3.定义省略号
      *  StrUtil.simpleFormat(t3, "ABCDEFGHIJKLM");  //Hello ABCDEF>>>!
      *  StrUtil.simpleFormat(t3, "星期六的黄昏");   //Hello 星期六>>>! 
      */
      sub : function(param, propName, propVal, context){
        var args = param.replace(/\s+/g, '').split(',');
        var max  = parseInt(args[0]);
        var mask = args[2] || "...";
        var byWidth = args.length > 1 && args[1] == "w";
        var maskLen, propLen;
        
        if(byWidth){
          maskLen = StrUtil.getStrWidth(mask);
          propLen = StrUtil.getStrWidth(propVal);
        }else{
          maskLen = mask.length;
          propLen = propVal.length;
        }
        
        if(propLen <= max){
          return propVal;
        }     if(maskLen >= max){
          return mask;
        }    
          
        return (
            byWidth
          ? StrUtil.cutStrByWidth(propVal, max - maskLen) + mask
          : propVal.substring(0, max - maskLen) + mask
        );
      }
    }var StrUtil = {
      /**
      * 获取字符串宽度(英文为一个宽度,中文两个).
      * @param  {String}str
      * @return {int}
      * @public
      */
      getStrWidth : function(str){
        if(!str){ return 0; }
       
        var i, c, ret = 0, len = str.length;
        for(i=0; i<len; i++){
          c = str.charCodeAt(i);
          ret += (c > 256 ? 2 : 1); 
        }
        
        return ret;
      },  /**
      * 根据其实位置和宽度截取字符串.
      * @param {String}str
      * @param {int}width
      * @param {int}[start]  截取开始位置, 默认为0
      */
      cutStrByWidth : function(str, width, start){
        if(!str || width <= 0) { return ''; }
        
        var i, len, code, end, size = 0, ret = [];
        
        start = start == undefined ? 0 
              : start < 0 ? str.length + start
              : start; 
        end = start + width;
        
        for(i=0, len=str.length; i<len; i++){
          code  = str.charCodeAt(i);
          size += (code > 256 ? 2 : 1);
          if(size >= start && size <= end){
            ret.push(str.charAt(i));
            if(size == end){ break; }
          }      
        }
        
        return ret.join('');  
      },  /**
      * 根据膜拜进行简单格式化.
      * @param  {String}temp
      * @param  {JSON|Object|...}args
      * @param  {JSON<String, Function>}[handlers]
      * @return {String}
      * @public
      * @example
      * var t  = "welcom #{0} #{1->map(f:小姐, else:先生)}";
      * var t1 = "welcom #{name} #{gender->map(f:小姐, else:先生)}";
      * var t2 = "全文 : #{message}\n"
      *        + "概要 : #{message->sub(12,w,...)}";         
      *
      * alert(StrUtil.simpleFormat(t, "王建波", 29));
      * alert(StrUtil.simpleFormat(t1, {name   : "王建波", age: 29 }));
      * alert(StrUtil.simpleFormat(t2, {message: "123456789ABCDEFG"}));  
      */ 
      simpleFormat : function(temp, args, handlers){
        var argc = arguments.length;
        if ( arguments.length == 1 ) { return temp }
        if ( arguments.length >  3 || typeof arguments[1] != "object" ) {
          args = [].slice.call(arguments, 1, argc);
          handlers = arguments[argc -1];
        }
            
        var reg = new RegExp((
            "\\\\#\\{|#\\{"        //匹配变量转义符\#{或变量开始#{
          +   "(\\w+)"             //属性名称
          +   "(?:->\\s*"          //属性后可选的内置方法调用比如:#{name->sub(5)}
          +     "(\\w+)\\s*\\("    //内置方法名称
          +       "("              //内置方法参数
          +          "(?:[^)}\"'\\n]*?|\".*?\"|'.*?')*"
          +       ")"
          +     "\\)"             
          +   ")?"                
          + "\\}"
        ), "gi");
        
        var valCache = {};    
        
        var context = {
          handlers : handlers,
          valCache : valCache
        };
        
        var replaceHandler = function(m, prop, fn, fnParam){
          var propVal, fnRet, ret;
          
          //对于转义符,直接返回"\"之后内容
          if( m == "\\#{" ) { return "#{" }
          
          //若已经计算过直接返回
          if(valCache.hasOwnProperty(m)){
            return valCache[m];
          }      
          
          if(prop) {          
            propVal = args[prop] != undefined 
                    ? String(args[prop]) 
                    : "";
            
            //若需要对返回值进行函数调用,返回函数调用结果
            if(fn && FmtHelper.hasOwnProperty(fn)){
              try{
                fnRet = FmtHelper[fn](
                  fnParam, 
                  prop, 
                  propVal, 
                  context
                );
              }catch(e){}
            }        ret = (fnRet == undefined || fnRet == null) ? propVal : fnRet;
          }else{
            ret = m;
          }
          
          valCache[m] = ret;      
          return ret;
        };       
        
        return temp.replace(reg, replaceHandler);  
      }
    }return StrUtil;
    })();window.onload = function(){
      alert(StrUtil.simpleFormat(
        "hello #{0}, #{1}!",
        "张三",
        "先生"
      ));
      
      alert(StrUtil.simpleFormat(
        "hello #{name}, #{title}!",
        {name : "张三", title : "先生"}
      ));  
      
      var params = {
        id : 'user-1',
        name   : '张三',
        gender : 'male',
        pic    : 'http://www.baidu.com/img/baidu_sylogo1.gif',
        details: (
            "主要是我还从没有系统的学过js,理论方面自<br/>"
          + "己对很多东西的理解很浅显。因为不想说提供<br/>"
          + "了些东东出来结果造成使用者的意料之外的错<br/>"
          + "误或降低性能和效率。也包括使用时的体验等等"
        )
      }  var temp = (
          "hello #{name} #{gender->map(female:小姐, else:先生)}<hr/>"
        + "<pre>"
        +  " id     : #{id}<br/>"
        +  " name   : #{name}<br/>"
        +  " gender : #{gender->map(female:女, else:男)}<br/>"
        +  " pic    : <img src='#{pic}' align='top'/><br/>"
        +  " summary: #{details->sub(20, l, >>>)}<br/>"
        +  " details: #{details}"
        + "</pre>"
      );  var output = StrUtil.simpleFormat(temp, params, {
        getWelcome : function(key, val){
          return "hello " + val + ' current time is :' + new Date();
        }
      });  document.getElementById('div1').innerHTML = output;
    };
      

  12.   

    这是类似于前端模板的实现呀。与类似于tmpl相比不知效率如何?