基於不對原生對象進行擴展的原則,搞了這個方便的處理字符串的對象。javascript
下面是第一類工廠,至關於mootools的Native方法。java
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屬性。api
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也有許多專門處理字符串的方法,咱們也把它們加持到超級字符串對象上。app
//爲超級字符串對象添加全局對象處理字符串的相關方法
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;
}
});
|
再添加一些有用的自定義方法:dom
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;
|
運行代碼ide
像字符串原有的方法與window處理字符串的相關方法就不廢話了,咱們看一下自定義方法的用法。函數
超級字符串對象 | |
---|---|
trim | 去除左右兩邊的空白 |
contains | 檢測string是否包含給定的子串 |
dasherize | 將字符串中的"_"代替成"-" |
camelize | 將字符串改爲駝峯風格 |
capitalize | 首字符大寫 |
startsWith | 檢測string以給定的子串開頭 |
endsWith | 檢測string以給定的子串結束 |
empty | 檢測string是否一個字符也沒有 |
blank | 檢測string是否所有由空白字符構成 |
times | 字符串乘法,傳入一個數字,做爲原字符串的倍數 |
相關連接:超級數組對象this