JS
包含了一套小型的可用在标准类型上的标准方法集。
concat
方法产生一个新数组,它包含一份 array
的浅复制,并把一个或多个参数 item
附加在其后。如果 item
是一个数组,那么它的每个元素会被分别添加。
var a = ['a','b','c'];
var b = [1,2,3];
var c = a.concat(b,true);
// c : ['a','b','c',1,2,3,true]
join
方法把一个 array
构造成一个字符串。它先把 array
中的每个元素构造成一个字符串,接着用一个 separator
分隔符把它们连接在一起。默认的 separator
是逗号 ,
。想要无间隔的连接,可以使用空字符串作为 separator
。
var a = ['a','b',1];
var c = a.join('');
// c : 'ab1'
pop
和 push
方法使得数组 array
可以像堆栈一样工作。 pop
方法移除 array
中的最后一个元素并返回该元素。如果是 array
是 empty
,它会返回 unidefined
。
var a = ['a','b','c'];
var c = a.pop();
// a : ['a','b'] ,且 c 为 'c'
pop
可以像这样实现:
Array.prototype.pop = function(){
return this.splice(this.length - 1,1)[0];
};
push
方法把一个或多个参数 item
附加到一个数组的尾部。和 concat
方法不同的是,它会修改 array
,如果参数 item
是一个数组,它会吧参数数组作为单个元素整个添加到数组中,并返回这个 array
的新长度值。
var a = ['a','b','c'];
var b = [1,2,3];
var c = a.push(b,true);
// a : ['a','b','c',[1,2,3],true]
// c : 5
push
可以这样实现:
Array.prototype.push = function () {
this.splice.apply(
this,
[this.length, 0].concat(Array.prototype.slice.apply(arguments))
);
return this.length;
};
reverse
方法反转 array
中的元素顺序,并返回 array
本身。
var a = ['a','b','c'];
var b = a.reverse();
// a 和 b 都是 : ['c','b','a']
shift
方法移除数组 array
中的第一个元素并返回该元素。如果这个数组 array
是空的,它就会返回 undefined
。shift
通常比 pop
慢得多(pop
是移除并返回最后一个元素)。
var a = ['a','b','c'];
var c = a.pop();
// a : ['b','c'] ,且 c 为 'a'
shift
可以像这样实现:
Array.prototype.shift = function(){
return this.splice(0,1)[0];
};
slice
方法对 array
中的一段进行浅复制。首先复制 array[start]
,一直复制到 array[end]
为止。 end
参数是可选的,默认值是该数组的 length
。如果两个参数中的任何一个是负数,array.length
会和它们相加,试图让它们成为非负数。如果 start
大于等于 length
,得到的结果将是一个新的空数组。字符串也有一个同名的方法。
var a = ['a','b','c'];
var b = a.slice(0,1); // b : ['a']
var c = a.slice(1); // c : ['b','c']
var d = a.slice(-3,-1); // d : ['a','b'] 相当于 (0,2)
sort
方法对 array
中的内容进行排序。但使用其默认的比较函数不能正确的给一组数字排序:
var n = [4,8,5,23,16,48];
n.sort();
// n : [16,23,4,48,5,8]
JS
的默认比较函数把要被排序的元素都视为字符串,所以当它比较这些数字的时候,会把它们转化为字符串,于是得到一个错误的结果。
不过,可用自己定义的比较函数来替换默认的比较函数。
var n = [4,8,5,23,16,48];
n.sort(function (a1, b1) {
return a1 - b1;
});
// n : [4,5,8,16,23,48]
这个比较函数中有两个参数,若比较函数返回负,则表示第一个参数该排在前面,返回正则表示第二个参数该排在前面。
这个函数可以使数字正确排序,但不能使字符串排序。若想给包含简单值的数组排序,可使用以下比较函数:
var m = ['aa','bb','a','c','Aa',4,8,23,16,44];
m.sort(function (a1, b1) {
if(a1 === b1){
return 0;
}
if(typeof a1 === typeof b1){
return a1 < b1 ? -1 : 1;
}
return typeof a1 < typeof b1 ? -1 : 1;
});
// m : [4,8,16,23,44,'Aa','a','aa','bb','c']
如果大小写不重要,可在比较函数中的比较之前先将两个运算数转化为小写。
若想使对象数组排序,可编如下比较函数:
//by 函数接收一个成员名字字符串作为参数,并返回一个可以用来对包含该成员的对象数组进行排序的比较函数
var by = function (name) {
return function (o,p) {
var a,b;
if(typeof o === 'object' && typeof p === 'object' && o && p){
a = o[name];
b = p[name];
if(a === b){
return 0;
}
if(typeof a === typeof b){
return a < b ? -1 : 1;
}
return typeof a < typeof b ? -1 : 1;
}else{
throw{
name:'Error',
message:'Expected an object when sorting by' + name
};
}
};
};
var s = [
{first:'Joe', last:'Besser'},
{first:'Moe', last:'Howard'},
{first:'Joe', last:'DeRita'},
{first:'Shemp', last:'Howard'},
{first:'Larry', last:'Fine'},
{first:'Curly', last:'Howard'}
];
s.sort(by('first'));
/*
s :
[
{first:'Curly', last:'Howard'}
{first:'Joe', last:'DeRita'},
{first:'Joe', last:'Besser'},
{first:'Larry', last:'Fine'},
{first:'Moe', last:'Howard'},
{first:'Shemp', last:'Howard'},
];
*/
上述的 sort
方法是不稳定的,所以下面的调用不能保证产生正确的序列:
排序的稳定性指的是排序后数组中的相等值的相对位置没有发生改变,而不稳定排序则会改变相等值的相对位置。
s.sort(by('first')).sort(by('last'));
若想要基于多个键值排序,需要修改 by
函数,让其接受两个参数,当主要的键值相等时,调用另一个 compare
方法比较次要的键值:
var by = function (name, minor) {
return function (o,p) {
var a,b;
if(typeof o === 'object' && typeof p === 'object' && o && p){
a = o[name];
b = p[name];
if(a === b){
return typeof minor === 'function' ? minor(o,p) : 0; //改变的位置
}
if(typeof a === typeof b){
return a < b ? -1 : 1;
}
return typeof a < typeof b ? -1 : 1;
}else{
throw{
name:'Error',
message:'Expected an object when sorting by' + name
};
}
};
};
var s = [
{first:'Joe', last:'Besser'},
{first:'Moe', last:'Howard'},
{first:'Joe', last:'DeRita'},
{first:'Shemp', last:'Howard'},
{first:'Larry', last:'Fine'},
{first:'Curly', last:'Howard'}
];
s.sort(by('last',by('first')));
/*
s :
[
{first:'Joe', last:'Besser'},
{first:'Joe', last:'DeRita'},
{first:'Larry', last:'Fine'},
{first:'Curly', last:'Howard'}
{first:'Moe', last:'Howard'},
{first:'Shemp', last:'Howard'},
];
*/
splice
方法从 array
中移除一个或多个元素,并用新的 item
替换它们。参数 start
是从数组 array
中移除元素的开始位置。参数 deleteCount
是要移除的元素个数。如果有额外的参数,那些 item
会插入到被移除元素的位置上。它返回一个包含被移除元素的数组。
var a = ['a','b','c'];
var r = a.splice(1,1,'ache','bug');
// a : ['a','ache','bug','c']
// r : ['b']
splice
可以像这样实现:
Array.prototype.splice = function (start,deleteCount) {
var max = Math.max,
min = Math.min,
delta,
element,
insertCount = max(arguments.length - 2,0),
k = 0,
len = this.length,
new_len,
result = [],
shift_count;
start = start || 0;
if(start < 0){
start += len;
}
start = max(min(start,len),0);
deleteCount = max(min(typeof deleteCount === 'number' ?
deleteCount : len, len - start), 0);
delta = insertCount - deleteCount;
new_len = len + delta;
while(k < deleteCount){
element = this[start + k];
if(element !== undefined){
result[k] = element;
}
k += 1;
}
shift_count = len - start - deleteCount;
if(delta < 0){
k = start + insertCount;
while(shift_count){
this[k] = this[k - delta];
k += 1;
shift_count -= 1;
}
this.length = new_len;
}else if(delta > 0){
k = 1;
while(shift_count){
this[new_len - k] = this[len - k];
k += 1;
shift_count -= 1;
}
this.length = new_len;
}
for(k = 0; k < insertCount; k++){
this[start + k] = arguments[k + 2];
}
return result;
};
unshift
方法像 push
方法一样,用于把元素添加到数组中,但是它把 item
插入到 array
的开始部分而不是尾部。它返回 array
新的 length
。
var a = ['a','b','c'];
var r = a.unshift('?','@');
// a : ['?','@','a','ache','bug','c']
// r : 5
unshift
可以像这样实现:
Array.prototype.unshift = function () {
this.splice.apply(this,
[0,0].concat(Array.prototype.slice.apply(arguments)));
return this.length;
};
apply
方法调用 function
,传递一个会被绑定到 this
上的对象和一个可选的数组作为参数。 apply
方法被用在 apply
调用模式 中。
//返回一个函数,调用这个函数就像调用那个对象的一个方法
Function.prototype.bind = function (that) {
var method = this,
slice = Array.prototype.slice,
args = slice.apply(arguments,[1]);
return function () {
return method.apply(that,
args.concat(slice.apply(arguments,[0])));
};
};
var x = function () {
return this.value;
}.bind({value:666});
alert(x()); // --> 666
toExponential
方法把这个number
转换成一个指数形式的字符串。可选参数 fractionDigits
控制其小数点后的数字位数。它的值必须在 0~20
:
document.write(Math.PI.toExponential() + '
'); // 3.141592653589793e+0
document.write(Math.PI.toExponential(0) + '
'); // 3e+0
document.write(Math.PI.toExponential(2) + '
'); // 3.14e+0
document.write(Math.PI.toExponential(7) + '
'); // 3.1415927e+0
document.write(Math.PI.toExponential(16) + '
'); // 3.1415926535897931e+0
toFixed
方法把这个 number
转换成一个十进制数形式的字符串。可选参数 fractionDigits
控制其小数点后的数字位数。它的值必须在 0~20
,默认值为 0
:
document.write(Math.PI.toFixed() + '
'); // 3
document.write(Math.PI.toFixed(0) + '
'); // 3
document.write(Math.PI.toFixed(2) + '
'); // 3.14
document.write(Math.PI.toFixed(7) + '
'); // 3.1415927
document.write(Math.PI.toFixed(16) + '
'); // 3.1415926535897931
toPrecision
方法把这个 number
转换成一个十进制数形式的字符串。可选参数 precision
控制数字的精度。它的值必须在 1~21
:
document.write(Math.PI.toPrecision() + '
'); // 3.141592653589793
document.write(Math.PI.toPrecision(2) + '
'); // 3.1
document.write(Math.PI.toPrecision(7) + '
'); // 3.141593
document.write(Math.PI.toPrecision(16) + '
'); // 3.141592653589793
toString
方法把这个 number
转换成字符串。可选参数 radix
控制基数。它的值必须在 2~36
,默认的 radix
是以 10
为基数的。 radix
最常用的是整数,但它可以用任意的数字。
document.write(Math.PI.toString() + '
'); // 3.141592653589793
document.write(Math.PI.toString(2) + '
'); // 11.001001000011111101101010100010001000010110100011
document.write(Math.PI.toString(8) + '
'); // 3.1103755242102643
document.write(Math.PI.toString(16) + '
'); // 3.243f6a8885a3
如果这个 object
包含一个名为 name
的属性,那么 hasOwnProperty
返回 true
。原型链中的同名属性是不会被检查的。这个方法对 name
就是 hasOwnProperty
时不起作用,此时会返回 false
。
var a = {member:true};
var b = Object.create(a);
var t = a.hasOwnProperty('member'); // true
var u = b.hasOwnProperty('member'); //false
var v = b.member; // true
其中,create 方法 是在之前定义的。
exec
方法是使用正则表达式最强大(但最慢)的方法。
如果它成功地匹配 regexp
和字符串 string
,它会返回一个数组。数组中下标为 0
的元素将包含正则表达式 regexp
匹配的子字符串。下标为 1
的元素是分组 1
捕获的文本,下标为 2
的元素是分组 2
捕获的文本,以此类推。
如果匹配失败,它会返回 null
。
如果 regexp
带有一个 g
标识(全局标识)的话,那么查找不是从这个字符的起始位置开始,而是从 regexp.lastIndex
(初始值为 0)位置开始。如果匹配成功,那么 regexp.lastIndex
会被设为该匹配后第一个字符的位置。不成功 regexp.lastIndex
会被重置为 0。
这就允许通过循环调用 exec
去查询一个匹配模式在一个字符串中发生了几次。需要注意的是,如果提前退出了循环,再次进入循环必须把 regexp.lastIndex
设为 0.而且, ^
因子仅匹配 regexp.lastIndex
为 0 的情况。
/*
把一个简单的 HTML 文本分解为标签和文本
对每个标签和文本,都产生一个数组包含如下:
[0] 整个匹配的标签和文本
[1] / ,如果有的话
[2] 标签名
[3] 属性,如果有任何属性的话
*/
var text = ''
+ 'This is bold<\/b>!<\/p><\/body><\/html>';
var tags = /[^<>]+|(\/?)([A-Za-z]+)([^<>]*)>/g;
var a,i;
while((a = tags.exec(text))){
for(i = 0; i < a.length; i++){
document.write(('[' + i + '] : ' + a[i]).entitytify());
document.write('
');
}
document.write('
');
}
/*
[0] :
[1] :
[2] : html
[3] :
[0] :
[1] :
[2] : body
[3] : bgcolor="linen"
[0] :
[1] :
[2] : p
[3] :
[0] : This is
[1] : undefined
[2] : undefined
[3] : undefined
[0] :
[1] :
[2] : b
[3] :
[0] : bold
[1] : undefined
[2] : undefined
[3] : undefined
[0] :
[1] : /
[2] : b
[3] :
[0] : !
[1] : undefined
[2] : undefined
[3] : undefined
[0] :
[1] : /
[2] : p
[3] :
[0] :
[1] : /
[2] : body
[3] :
[0] :
[1] : /
[2] : html
[3] :
*/
test
方法是使用正则表达式的最简单(和最快)的方法。如果该 regexp
匹配 string
,它返回 true
,否则,它返回 false
。不要对这个方法使用 g
标识:
var b = /&.+;/.test('frank & amp; beans');
// b: true
test
可以这样实现:
RegExp.prototype.test = function (string) {
return this.exec((string) !== null);
};
charAt
方法返回在 string
中 pos
位置的字符。如果 pos
小于 0
或大于对于字符串的长度 length
,它会返回空字符串。
var name = 'Curly';
var initial = name.charAt(0); // C
charAt
可以这样实现:
String.prototype.charAt = function(pos){
return this.slice(pos,pos + 1);
};
charCodeAt
与 charAt
一样,只不过它返回的不是一个字符串,而是以整数形式表示的在 string
中的 pos
位置处的字符的字符码位。如果 pos
小于 0
或大于对于字符串的长度 length
,它会返回 NaN
。
var name = 'Curly';
var initial = name.charCodeAt(0); // 67
concat
方法把其他字符串连在一起来构造一个新字符串。不过它很少被使用,因为 +
运算符更方便:
var s = 'C'.concat('a','t'); // s : Cat
indexOf
方法在 string
内查找另一个字符串 searchString
,如果它被找到,返回第一个匹配字符的位置,否则返回 -1
。可选参数 position
可设置从 string
的某个指定位置开始查找。
var text = 'Mississippi';
var p = text.indexOf('ss'); // 2
p = text.indexOf('ss',3); // 5
p = text.indexOf('ss',6); // -1
lastIndexOf
方法和 indexOf
方法类似,只不过它是从该字符串的末尾开始查找而不是从开头:
var text = 'Mississippi';
var p = text.lastIndexOf('ss'); // p : 5
p = text.lastIndexOf('ss',3); // p : 2 , 开始查找位置为 3
p = text.lastIndexOf('ss',6); // p : 5 , 开始查找位置为 5
localeCompare
方法比较两个字符串,如果 string
比字符串 that
小,那么结果为负。如果相等,结果为 0
。这有点类似于 array.sort
的比较函数约定。
var m = ['AAA','A','aa','a','Aa','aaa'];
m.sort(function (a1, b1) {
return a1.localeCompare(b1);
});
// m : a,A,aa,Aa,aaa,AAA
match
方法让字符串和一个正则表达式进行匹配。它根据 g
标识来决定如何进行匹配。如果没有 g
标识,那么调用 string.match(regexp)
的结果与调用 regexp.exec(string)
的结果相同。然而如果有带 g
标识,那么它生成一个包含所有匹配(除捕获分组之外)的数组:
var text = ''
+ 'This is bold<\/b>!<\/p><\/body><\/html>';
var tags = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g;
var a,i;
a = text.match(tags);
for(i = 0; i < a.length; i++){
document.write(('[' + i + '] : ' + a[i]).entitytify());
document.write('
');
}
/*
[0] :
[1] :
[2] :
[3] : This is
[4] :
[5] : bold
[6] :
[7] : !
[8] :
[9] :
[10] :
*/
replace
方法对 string
进行查找和替换操作,并返回一个新的字符串。参数 searchValue
可以是一个字符串或一个正则表达式对象。
如果它是一个字符串,那么 searchValue
只会在第一次出现的地方被替换。
var result = 'mother_in_law'.replace('_','-');
// result : mother-in_law
如果 searchValue
是一个正则表达式对象且带有 g
标识它会替换所有的匹配。如果没有带 g
标识,它仅会替换第一个匹配。
replaceValue
可以是一个字符串或是一个函数。如果 replaceValue
是一个字符串,字符 $
拥有特别的含义:
//捕获括号中的 3 个数字
var oldareacode = /\((\d{3})\)/g;
var p = '(555)666-1212'.replace(oldareacode,'$1-');
// p : 555-666-1212
美元符号序列 | 替换对象 |
---|---|
$$ |
$ |
$& |
整个匹配的文本 |
$number (如 $1 ) |
分组捕获的文本 |
$`` (只有一个 ` 符号,显示问题) |
匹配之前的文本 |
$' |
匹配之后的文本 |
如果 replaceValue
是一个函数,那么每遇到一个匹配函数就会被调用一次,而该函数返回的字符串会被用做替换文本。传递给这个函数第一个参数是整个被匹配的文本,第二个参数是分组 1 捕获的文本,再下一个参数是分组 2 捕获的文本,以此类推:
String.prototype.entitytify = function () {
var character = {
'<' : '<',
'>' : '>',
'&' : '&',
'"' : '"',
};
/*
返回 string.entitytify 方法,它返回调用替换方法的结果
它的 replaceValue 函数返回一个对象中查找一个字符的结果
这种对象的用法通常优于 switch 语句
*/
return function () {
return this.replace(/[<>&"]/g,function (c) {
return character[c];
});
};
}();
p = '<&>'.entitytify(); // p : <&>
search
方法和 indexOf
方法类似,只是它只接受一个正则表达式对象作为参数而不是一个字符串。如果找到匹配,它返回第一个匹配的首字符位置,如果没有找到匹配,则返回 -1
。此方法会忽略 g
标识,且没有 position
参数。
var text = 'he says " Any damn fool could';
var pos = text.search(/["']/); // pos : 8
slice
方法复制 string
的一部分来构造一个新的字符串。如果 start
参数是负数,它将与 string.length
相加。end
参数是可选的,且默认值是 string.length
。如果 end
参数是负数,它将与 length
相加。end
参数的值等于需要取的最后一个字符的位置加上 1
。若想要得到从位置 p
开始的 n
个字符,可使用 string.slice(p,p + n)
。
var text = 'he says " Any damn fool could';
var a = text.slice(10); // Any damn fool could
var a = text.slice(0,3); // he
var a = text.slice(-5); // could
split
方法把 string
分割成片段来创建一个字符串数组。可选参数 limit
可以限制被分割的片段数量。separator
参数可以是一个字符串或一个正则表达式。
如果 separator
是一个空字符,会返回一个单字符数组:
var digits = '0123456789';
var a = digits.split('',5);
// a : ['0','1','2','3','4']
分隔符两边的每个单元文本都会被复制到该数组中,此方法会忽略 g
标识。
var ip = '192.168.1.0';
var b = ip.split('.');
// b : ['192','168','1','0']
var c = '|a|b|c|'.split('|');
// c : ['','a','b','c','']
var text = 'last,first,middle';
var d = text.split(/\s*,\s*/);
// d : ['last','first','middle']
需要注意的是,来自分组捕获的文本会被包含在被分割的数组中:
var e = text.split(/\s*(,)\s*/);
// e : ['last',',','first',',','middle']
substring
的用法和 slice
一样,只是它不能处理负数参数,最好都使用 slice
。
toLowerCase
方法返回一个新字符串,这个 string
中的所有字母都被转换为小写。
toUpperCase
方法返回一个新字符串,这个 string
中的所有字母都被转换为大写。