💜《JavaScript 语言精粹》之方法篇

134 阅读11分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

他虽疯,但却有他的一套理论。 —— 威廉 · 莎士比亚,《丹麦王子,哈姆雷特的悲剧》(The Tagedy of Hamlet, Prince of Denmark)

JavaScript 包含了一套小型的可用在标准类型上的标准方法集。

8.1 Array

8.1.1 array.concat(item…)

concat方法产生一个新数组,它包含一份 array 的浅复制并把一个或多个参数 item 附加在其后。如果参数 item 是一个数组,那么它的每个元素会被分别添加。后面你还会看到和它功能类似的array.push(item…) 方法。

var a = ['a', 'b', 'c'];
var b = ['x', 'y', 'z'];
var c = a.concat(b, true);
// c 变成 ['a', 'b', 'c', 'x', 'y', 'z', true]

8.1.2 array.join(separator)

  • join 方法把一个 array 构造成一个字符串。
  • 默认的 separator 是逗号 ','
  • 要想做到无间隔的连接,我们可以使用空字符串作为 separator
var a = ['a', 'b', 'c'];
a.push('d');
var c = a.join('')
// c 是 'abcd';

8.1.3 array.pop()

  • poppush 方法使得数组 array 可以像堆栈一样工作。
  • pop 方法移出 array 中的最后一个元素并返回该元素。
  • 如果该 arrayempty,它会返回 undefined
var a = ['a', 'b', 'c'];
var c = a.pop();  // a is ['a', 'b'] & c is 'c'
// pop 可以像这样实现:
Array.method('pop' function() {
	return this.splice(this.length - 1, 1)[0]
})

8.1.4 array.push(item…)

  • push 方法把一个或多个参数 item 附加到一个数组的尾部。
  • 返回这个 array 的新长度值。
var a = ['a', 'b', 'c'];
var b = ['x', 'y', 'z'];
var c = a.push(b, true);
// a is ['a', 'b', 'c', ['x', 'y', 'z'], true];
// c is 5

// push 可以像这样实现
Array.method('push', function() {
	this.splice.apply(
		this,
		[this.length, 0].concat(Array.prototype.slice.apply(arguments)))
	return this.length
})

8.1.5 array.reverse()

  • reverse 方法反转 array 里的元素的顺序,并返回 array 本身。
var a = ['a', 'b', 'c'];
var b = a.reverse()
// a and b is ['c', 'b', 'a']

8.1.6 array.shift()

  • shift 方法移除数组 array 中的第 1 个元素并返回该元素。
  • 如果这个数组 array 是空的,它会返回 undefined
  • shift 通常比 pop 慢得多。
var a = ['a', 'b', 'c'];
var c = a.shift()
// a is ['b', 'c'] & c is 'a'

// shift 可以这样实现:
Array.method('shift', function() {
	return this.splice(0, 1)[0]
})

8.1.7 array.slice(start, end)

  • slice 方法对 array 中的一段做浅复制。
  • 复制 array[start],一直复制到 array[end]为止。
  • end 参数是可选的,默认值是该数组的长度 array.length
  • 如果 start 大于等于 array.length,得到的结果将是一个新的空数组。
var a = ['a', 'b', 'c'];
var b = a.slice(0, 1);  // b is ['a'];
var c = a.slice(1)  // c is ['b', 'c']
var d = a.slice(1, 2)  // d is ['b']

8.1.8 array.sort(comparefn)

sort 方法对 array 中的内容进行排序。它不能正确地给一组数字排序:

var n = [4, 8, 15, 16, 23, 42];
n.sort();
// n is [15, 16, 23, 4, 42, 8]

你可以使用自己的比较函数来替代默认的比较函数。你的比较函数应该接受两个参数,并且如果这两个参数相等则返回 0,如果第 1 个参数应该排列在前面,则返回一个负数,如果第 2 个参数应该排列在前面,则返回一个正数。

n.sort(function (a, b) {
	return a - b;
})
// n is [4, 8, 15, 16, 23, 42];

上面这个函数可以使数字正确排序,但它不能使字符串排序。如果我们想要给任何包含简单值的数组排序,必须要做更多的工作:

var m = ['aa', 'bb', 'a', 4, 8, 15, 16, 23, 42];
m.sort(function (a, b){
	if (a === b) {
		return 0;
	}
	if(typeof a === typeof b) {
		return a < b ? -1 : 1;
	}
	return typeof a < typeof b ? -1 : 1;
})
// m is [ 4, 8, 15, 16, 23, 42, 'a', 'aa', 'bb'];

如果大小写不重要,你的比较函数应该在比较之前先将两个运算数转化为小写。此外请参见本章后面的 string.localeCompare

8.1.9 array.splice(start, deleteCount, item…)

splice 方法从 array 中移除一个或多个元素,并用新的 item 替换它们。参数 start 是从数组 array 中移除元素的开始位置。参数 deleteCount 是要移除的元素个数。如果有额外的参数,那些 item 会插入到被移除元素的位置上。它返回一个包含被移除元素的数组。

splice 最主要的用处是从一个数组中删除元素。千万不要把 spliceslice 弄混了:

var a = ['a', 'b', 'c'];
var r = a.splice(1, 1, 'ache', 'bug');
// a is ['a', 'ache', 'bug', 'c']
// r is ['b']

8.1.10 array.unshift(item…)

unshift 方法像 push 方法一样,用于把元素添加到数组中,但它是把 item 插入到 array的开始部分而不是尾部。它返回 array 的新的 length

var a = ['a', 'b', 'c'];
var r = a.unshift('?', '@');
// a is ['?', '@', 'a', 'b', 'c'];
// r is 5

// unshift 可以像这样实现:
Array.method('unshift', function() {
	this.splice.apply(this,
		[0, 0].concat(Array.prototype.slice.apply(arguments)));
	return this.length;
})

8.2 Function

8.2.1 function.apply(thisArg, argArray)

  • apply 方法调用 function,传递一个会被绑定到 this 上的对象和一个可选的数组作为参数。

  • apply 方法被用在 apply 调用模式中(参见第 4 章)。

Function.method('bind', function(that) {
// 返回一个函数,调用这个函数就像调用那个对象的一个方法。
	var method = this,
		slice = Array.prototype.slice,
		args = slice.apply(arguments, [1]);
	return method.apply(that,
			args.concat(slice.apply(arguments, [0])));
});
var x = function() {
	return this.value;
}.bind({value: 666})
alert(x());  // 666

8.3 Number

8.3.1 number.toExponential(fractionDigits)

  • toExponential 方法把这个 number 转换成一个指数形式的字符串。
  • 可选参数 fractionDigits 控制其小数点后的数字位数。
  • 它的值必须在 0 ~ 20。
document.writeln(Math.PI.toExponential(0))   // 3e+0
document.writeln(Math.PI.toExponential(2))   // 3.14e+0
document.writeln(Math.PI.toExponential(7))   // 3.1415927e+0
document.writeln(Math.PI.toExponential(16))  // 3.1415926535897930e+0
document.writeln(Math.PI.toExponential())    // 3.141592653589793e+0

8.3.2 number.toFixed(fractionDigits)

  • toFixed 方法把这个 number 转换成为一个十进制数形式的字符串。
  • 可选参数 fractionDigits 控制其小数点后的数字位数。
  • 它的值必须在 0 ~ 20,默认为 0。
document.writeln(Math.PI.toFixed(0))   // 3
document.writeln(Math.PI.toFixed(2))   // 3.14
document.writeln(Math.PI.toFixed(7))   // 3.1415927
document.writeln(Math.PI.toFixed(16))  // 3.1415926535897930
document.writeln(Math.PI.toFixed())    // 3

8.3.3 number.toPrecision(precision)

  • toPrecision 方法把这个 number 转换成为一个十进制数形式的字符串。
  • 可选参数 precision 控制数字的精度。
  • 它的值必须在 0 ~ 21。
document.writeln(Math.PI.toPrecision(2))   // 3.1
document.writeln(Math.PI.toPrecision(7))   // 3.141593
document.writeln(Math.PI.toPrecision(16))  // 3.141592653589793
document.writeln(Math.PI.toPrecision())    // 3.141592653589793

8.3.4 number.toString(radix)

  • toString 方法把这个 numebr 转换成为一个字符串。
  • 可选参数 radix 控制基数。
  • 它的值必须在 2 ~ 36,默认值的 radix 是以10为基数的。
  • radix 参数最常用的是整数,但是它可以用任意的数字。
document.writeln(Math.PI.toString(2))   // 11.001001000011111101101010100010001000010110100011
document.writeln(Math.PI.toString(8))   // 3.1103755242102643
document.writeln(Math.PI.toString(16))  // 3.243f6a8885a3
document.writeln(Math.PI.toString())    // 3.141592653589793

8.4 Object

8.4.1 object.hasOwnProperty(name)

  • 如果这个 object 包含一个名为 name 的属性,那么 hasOwnProperty 方法返回 true
  • 原型链中的同名属性是不会被检查的。
  • 这个方法对 name 就是 “hasOwnProperty”时不起作用,此时会返回 false
var a = {member: true};
var b = Object.create(a);
var t = a.hasOwnProperty('member')  // t is true
var u = b.hasOwnProperty('member')  // u is false
var v = b.member  // v is true

8.5 RegExp

8.5.1 regexp.exec(string)

  • exec 方法是使用正则表达式的最强大(和最慢)的方法。如果它成功地匹配 regexp 和字符串 string,它会返回一个数组。
  • 数组中下标为 0 的元素将包含正则表达式 regexp 匹配的子字符串。下标为 1 的元素是分组 1 捕获的文本,依此类推。如果匹配失败,它会返回 null
  • 如果 regexp 带一个 g 标识(全局标识),事情会变得更加复杂。
  • 查找不是从这个字符串的起始位置开始,而是从 regexp.lastIndex (初始值为 0)位置开始。
  • 如果匹配成功,那么 regexp.lastIndex 将被设置为该匹配后第一个字符的位置。
  • 不成功的匹配会重置 regexp.lastIndex 为 0。

8.5.2 regexp.test(string)

  • test 方法是使用正则表达式的最简单(和最快)的方法。
  • 如果该 regexp 匹配 string,它返回 true;否则,它返回 false
  • 不要对这个方法使用 g 标识。
var b = /&.+;/.test('frank &amp; beans')  // b is true
// test 可以像这样实现
RegExp.method('test', function(string) {
	return this.exec(string) !== null;
})

8.6 String

8.6.1 string.charAt(pos)

  • charAt 方法返回在 stringpos 位置处的字符。
  • 如果 pos 小于 0 或大于等于字符串的长度 string.length,它会返回空字符串。
  • JavaScript 没有字符类型
  • 这个方法返回的结果是一个字符串。
var name = 'Curly';
var initial = name.charAt(0);  // initial is 'C'
// charAt 可以像这样实现
String.method('charAt', function(string) {
	return this.slice(pos, pos + 1);
})

8.6.2 string.charCodeAt(pos)

  • charCodeAt 方法同 charAt 一样,只不过它返回的不是一个字符串,而是以整数形式表示的在 string 中的 pos 位置处的字符的字符码位。
  • 如果 pos 小于 0 或大于等于字符串的长度 string.length,它会返回 NaN
var name = 'Curly';
var initial = name.charCodeAt(0)  // initial is 67

8.6.3 string.concat(string…)

  • concat 方法把其他的字符串连接在一起来构造一个新的字符串。
  • 它很少被使用,因为用 + 运算符更为方便。
var s = 'C'.concat('a', 's'); // s is Cat

8.6.4 string.indexOf(searchString, position)

  • indexOf 方法在 string 内查找另一个字符串 searchString
  • 如果它被找到,返回第一个匹配字符的位置,否则返回 -1
  • 可选参数 position 可设置从 string 的某个指定的位置开始查找。
var text = 'Mississippi';
var p = text.indexOf('ss'); // p is 2
p = text.indexOf('ss' 3);   // p is 5
p = text.indexOf('ss', 6);  // p is -1

8.6.5 string.lastIndexOf(searchString, position)

  • lastIndexOfindexOf 方法类似,只不过它是从该字符串的末尾开始查找而不是从开头。
var text = 'Mississippi';
var p = text.indexOf('ss'); // p is 5
p = text.indexOf('ss' 3);   // p is 2
p = text.indexOf('ss', 6);  // p is 5

8.6.6 string.match(regexp)

  • match 方法让字符串和一个正则表达式进行匹配。
  • 它依据 g 标识来决定如何进行匹配。
  • 如果没有 g 标识,那么调用 string.match(regexp) 的结果与调用 regexp.exec(string) 的结果相同。
  • 如果 regexp 带有 g 标识,那么它生产一个包含所有匹配(除捕获分组之外的数组)。

8.6.7 string.replace(searchValue, replaceValue)

  • replace 方法对 string 进行查找和替换操作,并返回一个新的字符串。
  • 参数 searchValue 可以是一个字符串或一个正则表达式对象。
  • 如果它是一个字符串,那么 searchValue 只会在第 1 次出现的地方被替换
  • 如果 searchValue 是一个正则表达式并且带有 g 标识,它会替换所有的匹配。
  • 如果没有带 g 标识,它会仅替换第 1 个匹配。
  • relpaceValue 可以是一个字符串或一个函数。
  • 如果 relpaceValue 是一个字符串,字符$ 拥有特别的意义。
  • 如果 relpaceValue 是一个函数,那么每遇到一次匹配函数就会被调用一次,而该函数返回的字符串会被用做替换文本。
  • 传递给这个函数的第 1 个参数是整个被匹配的文本,第 2 个参数是分组 1 捕获的文本,依此类推。

8.6.8 string.search(regexp)

  • search 方法和 indexOf 方法类似
  • 它接受一个正则表达式对象作为参数而不是一个字符串
  • 如果找到匹配,它返回第 1 个匹配的首字符位置。
  • 如果没有找到匹配,则返回 -1.
  • 次方法会忽略 g 标识,且没有 position 参数
var text = 'and in it he says "Any damn fool could';
var pos = text.search(/["']/); // pos is 18

8.6.9 string.slice(start, end)

  • slice 方法复制 string 的一部分来构造一个新的字符串。
  • 如果 start 参数是负数,它将与 string.length 相加。
  • end 参数是可选的,且默认值是 string.length。如果 end 参数是负数,那么它将与 string.length 相加。end 参数等于你要取的最后一个字符的位置值加上 1。
var text = 'and in it he says "Any damn fool could';
var a = text.slice(18);   // a is '"Any damn fool could'
var b = text.slice(0, 3)  // b is 'and'
var c = text.slice(-5);   // c is 'could'
var d = text.slice(19, 32) // d is 'Any damn fool'

8.6.10 string.split(separator, limit)

  • split 方法把这个 string 分割成片段来创建一个字符串数组。
  • 可选参数 limit 可以限制被分割的片段数量
  • separator 参数可以是一个字符串或一个正则表达式。

如果 separator 是一个空字符,会返回一个单字符的数组:

var digits = '0123456789';
var a = digits.split('', 5);  // a is ['0', '1', '2', '3', '4']

否则,此方法会在 string 中查找所有 separator 出现的地方。分隔符两边的每个单元文本会被复制到该数组中。此方法会忽略 g 标识。

var ip = '192.168.1.0';
var b = ip.split('.')  // b is ['192', '168', '1', '0']

var c = '|a|b|c'.split('|')  // c is ['', 'a', 'b', 'c', '']
var text = 'last, first ,middle';
var d = text.split(/\s*(,)\s*/);  // d is ['last', ',', 'first', ',', 'middle']

separator 是一个正则表达式时,有一些 JavaScript 的实现在输出数组中会排除掉空字符串

var f = 'a|b|c'.split(/\|/);
// 在一些系统中, f 是 ['', 'a', 'b', 'c', '']
// 在另一些系统中,f is ['a', 'b', 'c']

8.6.11 string.substring(start, end)

  • substring 的用法和 slice 方法一样,只是它不能处理负数参数。
  • 没有任何理由去使用 substring 方法。请用 slice 替代它。

8.6.12 string.toLocaleLowerCase()

  • toLocaleLowerCase 方法返回一个新字符串,它使用本地化的规则把这个 string 中的所有字母转换为小写格式。

8.6.13 string.toLocaleUpperCase()

  • toLocaleUpperCase 方法返回一个新字符串,它使用本地化的规则把这个 string 中的所有字母转换成大写格式。

8.6.14 string.toLowerCase()

  • toLowerCase 方法返回一个新的字符串,这个 string 中的所有字母都被转换为小写格式。

8.6.15 string.toUpperCase()

  • toUpperCase 方法返回一个新的字符串,这个 string 中的所有字母都被转换为大写格式。

8.6.16 String.fromCharCode(Char…)

  • String.fromCharCode 函数根据一串数字编码返回一个字符串。