javascript 超级字符串对象

超级字符串
本文介绍了一个强大的字符串处理对象,通过封装和扩展实现了丰富的字符串操作方法,包括常用字符串方法及自定义功能。

基于不对原生对象进行扩展的原则,搞了这个方便的处理字符串的对象。

下面是第一类工厂,相当于mootools的Native方法。

 
      var dom = {},//命名空间
      slice = Array.prototype.slice;
      dom.mixin = function (obj, bag) {
        if (arguments.length === 1) {
          bag = obj;
          obj = this;
        };
        if (obj && bag && typeof bag === 'object') {
          for (var p in bag) {
            if(bag.hasOwnProperty(p))
              obj[p] = bag[p];
          }
        };
        if (!+"\v1") {//IE不能在for...in循环中遍历toString与valueOf属性,需要单独处理
          var t = bag.toString,v = bag.valueOf,op = Object.prototype;
          if (bag.hasOwnProperty("toString") && typeof t === "function" && t !== op.toString)
            obj.toString = t;
          if (bag.hasOwnProperty("valueOf") && typeof v === "function" && v !== op.valueOf)
            obj.valueOf = v;
        }
        return obj;
      };
      dom.factory = function(obj){//第一类工厂
        var init = obj.init,
        klass = function() {
          //如果传入参数与当前类是同一类型,则直接返回
          if(arguments.length === 1 && arguments[0] instanceof klass)
            return arguments[0];
          return new klass.fn.init(arguments);
        }
        klass.fn = klass.prototype = {
          init :init,
          constructor: klass
        };
        klass.fn.init.prototype = klass.fn;
        delete obj.klass;delete obj.init;
        dom.mixin(klass.fn, obj);
        //用于扩展原型方法
        klass.mixin = function(bag){
          dom.mixin(this.fn,bag);
          return this;
        };
        klass.alias = function(oldName, newName){
          var bag = {};
          if (dom.isString(oldName) && dom.isString(newName)){
            var method = this.fn[oldName]
            if (!!method){
              bag[newName] = method;
              return this.mixin(bag);
            };
          };
          //如果是一个属性包,如Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
          bag = oldName;
          for (var name in bag)
            if(bag.hasOwnProperty(name))
              this.alias(name,bag[name]);
          return this;
        };
        klass.staticizeWithout = function(arr){
          var conditions = {},keys = arr || [],me = this;
          for(var i=0,n = keys.length;i<n;i++){
            conditions[keys[i]] = 1;
          }
          dom.each(me.fn,function(method, name){
            if(!conditions[name] && dom.isFunction(me.fn[name]) && dom.isUndefined(me[name])&&
              name !== 'init' && name !== 'toString' && name !== 'valueOf' ){
              me[name] = function () {
                var args = dom.toArray(arguments),
                caller = args.shift();
                method.name = name; //为其泛化方法添加一个name属性
                return method.apply(me(caller), args);
              }
            }
          });
          return me;
        }
        return klass;
      };
      dom.mixin(new function(){
        var _toString = Object.prototype.toString,
        _slice = Array.prototype.slice,
        _push = Array.prototype.push,
        is = function(obj,type) {
          return _toString.call(obj).match(/^\[object\s(.*)\]$/)[1] === type;
        }
        return {
          isArray: function (obj) {
            return is(obj,"Array");
          },
          isFunction: function (obj) {
            return is(obj,"Function") ;
          },
          isNumber: function (obj) {
            return is(obj,"Number") ;
          },
          isString: function (obj) {
            return is(obj,"String") ;
          },
          isUndefined: function (obj) {
            return  obj === void(0);
          },
          each: function (obj, fn, bind) {
            for (var key in obj) //只遍历本地属性
              if (obj.hasOwnProperty(key))
                fn.call(bind, obj[key], key, obj);
          },
          isArrayLike : function (obj) {//包括Array
            if(dom.isArray(obj) || obj.callee) return true;
            if(is(obj,'NodeList')) return true;
            if(is(obj,'HTMLCollection')) return true;
            //不能为字符串,不能为window,具有length属性
            if(dom.isNumber(obj.length) && !dom.isString(obj) && !obj.eval){
              if(obj.nextNode || obj.item)
                return true;
              var n = obj.length - 1 < 0 ? 0 : obj.length - 1 ;
              //如果是具有数字键或length属性的对象,如jQuery对象
              if(obj.hasOwnProperty(n) && obj.hasOwnProperty(0))
                return true
              return false;
            }
            return false;
          },
          toArray : function (arr) { //把普通对象变成原生数组对象
            if(arguments.length === 0 || arr === null){
              return [];
            }else if(arr.callee){//如果是Arguments对象
              return _slice.call(arr);
            }else if(dom.isArray(arr)){//如果Array对象返回一个克隆
              return arr.concat();
            }else if(dom.isArrayLike(arr)){
              try{//jQuery对象,dom对象,el.getElementsByTagName得到的HTMLCollection
                //与el.childNodes得到的NodeList
                return _slice.call(arr);
              }catch(e){//IE用slice处理元素或节点集合会出错,只能慢慢拷贝
                var ret = [], i = arr.length;
                while (i) ret[--i] = arr[i]; //Clone数组
                return ret;
              }
            }else {//普通函数,单个元素节点,字符串,数字,window对象
              return [arr];
            }
          },
          setArray: function (els) { //把普通对象变成类数组对象
            this.length = 0;
            _push.apply(this, els);
            return this;
          }
        }
      });
      dom.win = window;

类工厂的能力很强大,生成的类拥有自我扩展的能力。下面是超级字符串的核心方法,分别为入口函数,构造函数,toString,valueOf与一个重要的setArray方法,用于设置charAt的索引值与length属性。

 
      var string = dom.factory({
        init: function (obj) {
          this.setArray(obj[0].split(''));
          return this;
        },
        toString: function () {
          return this.valueOf();
        },
        valueOf: function () {
          return Array.prototype.join.call(this, '');
        },
        setArray: dom.setArray
      });

再把字符串的泛化方法加持到其上,让其伪装成字符串对象。

 
      //为超级字符串对象添加原生字符串对象的泛化方法
      dom.each("charAt,charCodeAt,concat,indexOf,lastIndexOf,match,\
              replace,search,slice,split,substr,substring,toLowerCase,\
              toUpperCase,fontcolor,big,small,anchor,link,bold,italics,\
              sub,sup,fixed,fontsize,strike".match(/\w+/g),
      function (name) {
        string.fn[name] = function () {
          var method = String.prototype[name],
          args = dom.toArray(arguments),
          ret = method.apply(this.valueOf(), args);
          if (dom.isString(ret))
            return string(ret)
          return ret;
        }
      });

全局变量window也有许多专门处理字符串的方法,我们也把它们加持到超级字符串对象上。

 
      //为超级字符串对象添加全局对象处理字符串的相关方法
      dom.each("parseInt,parseFloat,escape,unescape,eval,decodeURI,\
              encodeURI,decodeURIComponent,encodeURIComponent".match(/\w+/g),
      function (name) {
        string.fn[name] = function () {
          var ret = dom.win[name](this.valueOf());
          if (dom.isString(ret)) //确保返回超级字符串对象
            return string(ret);
          return ret;
        }
      });

再添加一些有用的自定义方法:

 
      string.mixin({
        trim: function () {
          var str = this.valueOf();
          if (String.trim) {
            return string(String.trim(str))
          } else {
            str = str.replace(/^\s\s*/, '');
            var ws = /\s/,
            i = str.length;
            while (ws.test(str.charAt(--i)));
            return string(str.slice(0, i + 1));
          };
        },
        dasherize: function () {
          return this.replace(/_/g, '-');
        },
        camelize : function (str) {
          return this.replace(/-([a-z])/g, function($1,$2){
            return $2.toUpperCase()
          });
        },
        capitalize: function () {
          return this.replace(/\S+/g, function ($1) {
            return $1.charAt(0).toUpperCase() + $1.slice(1);
          });
        },
        contains: function (segment) {
          return this.indexOf(segment) !== -1;
        },
        startsWith: function (pattern) {
          return this.indexOf(pattern) === 0;
        },
        endsWith: function (pattern) {
          var d = this.length - pattern.length;
          return d >= 0 && this.lastIndexOf(pattern) === d;
        },
        empty: function () {
          return this.valueOf() === '';
        },
        blank: function () {
          return /^\s*$/.test(this.valueOf());
        },
        times: function (n) {
          if (n == 1)
            return this;
          var s = this.times(Math.floor(n / 2));
          s += s;
          if (n % 2) {
            s += this;
          }
          return string(s);
        }
      });
      //静态化超级字符串对象的大部分原型方法
      string.staticizeWithout(["setArray"]);
      dom.string = string;
<!doctype html> <html dir="ltr" lang="zh-CN" > <head id="head"> <meta charset="utf-8"/> <title>超级字符串对象 by司徒正美</title> <script type="text/javascript" charset="utf-8"> var dom = {},//命名空间 slice = Array.prototype.slice; dom.mixin = function (obj, bag) { if (arguments.length === 1) { bag = obj; obj = this; }; if (obj && bag && typeof bag === 'object') { for (var p in bag) { if(bag.hasOwnProperty(p)) obj[p] = bag[p]; } }; if (!+"\v1") {//IE不能在for...in循环中遍历toString与valueOf属性,需要单独处理 var t = bag.toString,v = bag.valueOf,op = Object.prototype; if (bag.hasOwnProperty("toString") && typeof t === "function" && t !== op.toString) obj.toString = t; if (bag.hasOwnProperty("valueOf") && typeof v === "function" && v !== op.valueOf) obj.valueOf = v; } return obj; }; dom.factory = function(obj){//第一类工厂 var init = obj.init, klass = function() { //如果传入参数与当前类是同一类型,则直接返回 if(arguments.length === 1 && arguments[0] instanceof klass) return arguments[0]; return new klass.fn.init(arguments); } klass.fn = klass.prototype = { init :init, constructor: klass }; klass.fn.init.prototype = klass.fn; delete obj.klass;delete obj.init; dom.mixin(klass.fn, obj); //用于扩展原型方法 klass.mixin = function(bag){ dom.mixin(this.fn,bag); return this; }; klass.alias = function(oldName, newName){ var bag = {}; if (dom.isString(oldName) && dom.isString(newName)){ var method = this.fn[oldName] if (!!method){ bag[newName] = method; return this.mixin(bag); }; }; //如果是一个属性包,如Hash.alias({keyOf: 'indexOf', hasValue: 'contains'}); bag = oldName; for (var name in bag) if(bag.hasOwnProperty(name)) this.alias(name,bag[name]); return this; }; klass.staticizeWithout = function(arr){ var conditions = {},keys = arr || [],me = this; for(var i=0,n = keys.length;i<n;i++){ conditions[keys[i]] = 1; } dom.each(me.fn,function(method, name){ if(!conditions[name] && dom.isFunction(me.fn[name]) && dom.isUndefined(me[name])&& name !== 'init' && name !== 'toString' && name !== 'valueOf' ){ me[name] = function () { var args = dom.toArray(arguments), caller = args.shift(); method.name = name; //为其泛化方法添加一个name属性 return method.apply(me(caller), args); } } }); return me; } return klass; }; dom.mixin(new function(){ var _toString = Object.prototype.toString, _slice = Array.prototype.slice, _push = Array.prototype.push, is = function(obj,type) { return _toString.call(obj).match(/^\[object\s(.*)\]$/)[1] === type; } return { isArray: function (obj) { return is(obj,"Array"); }, isFunction: function (obj) { return is(obj,"Function") ; }, isNumber: function (obj) { return is(obj,"Number") ; }, isString: function (obj) { return is(obj,"String") ; }, isUndefined: function (obj) { return obj === void(0); }, each: function (obj, fn, bind) { for (var key in obj) //只遍历本地属性 if (obj.hasOwnProperty(key)) fn.call(bind, obj[key], key, obj); }, isArrayLike : function (obj) {//包括Array if(dom.isArray(obj) || obj.callee) return true; if(is(obj,'NodeList')) return true; if(is(obj,'HTMLCollection')) return true; //不能为字符串,不能为window,具有length属性 if(dom.isNumber(obj.length) && !dom.isString(obj) && !obj.eval){ if(obj.nextNode || obj.item) return true; var n = obj.length - 1 < 0 ? 0 : obj.length - 1 ; //如果是具有数字键或length属性的对象,如jQuery对象 if(obj.hasOwnProperty(n) && obj.hasOwnProperty(0)) return true return false; } return false; }, toArray : function (arr) { //把普通对象变成原生数组对象 if(arguments.length === 0 || arr === null){ return []; }else if(arr.callee){//如果是Arguments对象 return _slice.call(arr); }else if(dom.isArray(arr)){//如果Array对象返回一个克隆 return arr.concat(); }else if(dom.isArrayLike(arr)){ try{//jQuery对象,dom对象,el.getElementsByTagName得到的HTMLCollection //与el.childNodes得到的NodeList return _slice.call(arr); }catch(e){//IE用slice处理元素或节点集合会出错,只能慢慢拷贝 var ret = [], i = arr.length; while (i) ret[--i] = arr[i]; //Clone数组 return ret; } }else {//普通函数,单个元素节点,字符串,数字,window对象 return [arr]; } }, setArray: function (els) { //把普通对象变成类数组对象 this.length = 0; _push.apply(this, els); return this; } } }); dom.win = window; var string = dom.factory({ init: function (obj) { this.setArray(obj[0].split('')); return this; }, toString: function () { return this.valueOf(); }, valueOf: function () { return Array.prototype.join.call(this, ''); }, setArray: dom.setArray }); //为超级字符串对象添加原生字符串对象的泛化方法 dom.each("charAt,charCodeAt,concat,indexOf,lastIndexOf,match,\ replace,search,slice,split,substr,substring,toLowerCase,\ toUpperCase,fontcolor,big,small,anchor,link,bold,italics,\ sub,sup,fixed,fontsize,strike".match(/\w+/g), function (name) { string.fn[name] = function () { var method = String.prototype[name], args = dom.toArray(arguments), ret = method.apply(this.valueOf(), args); if (dom.isString(ret)) return string(ret) return ret; } }); //为超级字符串对象添加全局对象处理字符串的相关方法 dom.each("parseInt,parseFloat,escape,unescape,eval,decodeURI,\ encodeURI,decodeURIComponent,encodeURIComponent".match(/\w+/g), function (name) { string.fn[name] = function () { var ret = dom.win[name](this.valueOf()); if (dom.isString(ret)) //确保返回超级字符串对象 return string(ret); return ret; } }); string.mixin({ trim: function () { var str = this.valueOf(); if (String.trim) { return string(String.trim(str)) } else { str = str.replace(/^\s\s*/, ''); var ws = /\s/, i = str.length; while (ws.test(str.charAt(--i))); return string(str.slice(0, i + 1)); }; }, dasherize: function () { return this.replace(/_/g, '-'); }, camelize : function (str) { return this.replace(/-([a-z])/g, function($1,$2){ return $2.toUpperCase() }); }, capitalize: function () { return this.replace(/\S+/g, function ($1) { return $1.charAt(0).toUpperCase() + $1.slice(1); }); }, contains: function (segment) { return this.indexOf(segment) !== -1; }, startsWith: function (pattern) { return this.indexOf(pattern) === 0; }, endsWith: function (pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; }, empty: function () { return this.valueOf() === ''; }, blank: function () { return /^\s*$/.test(this.valueOf()); }, times: function (n) { if (n == 1) return this; var s = this.times(Math.floor(n / 2)); s += s; if (n % 2) { s += this; } return string(s); } }); //静态化超级字符串对象的大部分原型方法 string.staticizeWithout(["setArray"]); dom.string = string; window.onload = function(){ var assert = document.getElementById("assert"); if(!assert){ assert = document.createElement("ul"); assert.i = 0; var item = document.createElement("li"); document.body.insertBefore(assert,null); } var test = function(str){ var li = item.cloneNode(false); assert.appendChild(li); li.innerHTML = str; assert.i++; li.style.backgroundColor = assert.i%2 === 1? "#e6e6e6" : "#D0E4FC"; }; var a = string("司徒正美") test("测试charAt方法"); test(a.charAt(0)); test("测试charCodeAt方法"); test(a.charCodeAt(0)); test("测试concat方法"); test(a.concat("罗浮宫")); test("测试indexOf方法"); test(a.indexOf("美")); test("测试lastIndexOf方法"); test(a.lastIndexOf("美")); test("测试match方法"); test(a.match(/\S/g)); test("测试replace方法"); test(a.replace("司徒","使徒")); test("测试search方法"); test(a.search("徒")); test("测试split方法"); test(a.split(/\正/)); test("测试slice方法"); test(a.slice(1,3)) test("测试substr方法"); test(a.substr(1,3)); test("测试substring方法"); test(a.substring(1,3)); var b = string(" 10.23SHITOU_nasami "); test("测试toLowerCase方法"); test(b.toLowerCase()); test("测试toUpperCase方法"); test(b.toUpperCase(1,3)) test("测试fontsize方法"); test(a.fontsize(6)); test("测试fontcolor方法"); test(a.fontcolor("red")); test("测试big方法"); test(a.big()); test("测试small方法"); test(a.small()); test("测试anchor方法"); test(a.anchor('myanchor')); test("测试link方法"); test(a.link('http://www.cnblogs.com/rubylouvre/')); test("测试bold方法"); test(a.bold()); test("测试italics方法"); test(a.italics()); test("测试sub方法"); test(a.sub()); test("测试sup方法"); test(a.sup()); test("测试fixed方法"); test(a.fixed()); test("测试strike方法"); test(a.strike()); test("测试parseInt方法"); test(b.parseInt()); test("测试parseFloat方法"); test(b.parseFloat()); test("测试escape方法"); test(string('Visit W3School!').escape()); test("测试unescape方法"); test(string('Visit%20W3School%21').unescape()); test("测试eval方法"); test("--------自行去掉注释检验吧--------"); // test(string("alert('这是eval出来的!')").eval()) test("测试encodeURI方法"); test(string('Visit W3School!').encodeURI()); test("测试decodeURI方法"); test(string('Visit%20W3School%21').decodeURI()); test("测试encodeURI方法"); test(string('Visit W3School!').encodeURI()); test("测试decodeURI方法"); test(string('Visit%20W3School%21').decodeURI()); test("测试encodeURIComponent方法"); test(string('http://www.cnblogs.com/rubylouvre/').encodeURIComponent()); test("测试decodeURIComponent方法"); test(string('http%3A%2F%2Fwww.cnblogs.com%2Frubylouvre%2F').decodeURIComponent()); test("测试trim方法"); test("|"+b.trim()+"|"); test("测试dasherize方法"); test(b.dasherize()); test("测试camelize方法"); test(b.dasherize().toLowerCase().camelize()); test("测试contains方法"); test(b.contains('nasami')); test("测试startsWith方法"); test(a.startsWith('司徒')); test("测试endsWith方法"); test(a.endsWith('正美')); test("测试empty方法"); test(a.empty()); test("测试blank方法"); test(string(' ').blank()); test("测试times方法"); test(a.times(4)); } </script> </head> <body> </body> </html>

运行代码

像字符串原有的方法与window处理字符串的相关方法就不废话了,我们看一下自定义方法的用法。

超级字符串对象
trim去除左右两边的空白
contains检测string是否包含给定的子串
dasherize将字符串中的"_"代替成"-"
camelize将字符串改成驼峰风格
capitalize首字符大写
startsWith检测string以给定的子串开头
endsWith检测string以给定的子串结束
empty检测string是否一个字符也没有
blank检测string是否全部由空白字符构成
times字符串乘法,传入一个数字,作为原字符串的倍数

相关链接:超级数组对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值