Obeta

JavaScript中的replace你真的知道怎么用吗

实际开发中我们会经常用到字符串的替换方法String.prototype.replace,但是并没有彻底的了解它的用法,今天来巩固一下,加深对他的理解.

replace()方法将匹配的部分替换到给定的值,然后返回一个新的字符串.这个给定的值可以是三种类型:string,RegExp,function.

需要注意的是原始值并没有改变.

语法

str.replace(regexp|substr, newSubstr|function);

参数解析:

  • regexp: 一个正则对象或者正则字符串,匹配的部分可以用newSubstr或者指定的function返回值替换.
  • substr: 一个字符串对象,因为不是正则,所以只会替换第一个匹配的字符串.
  • newSubstr: 由这个字符串来替换regexpsubstr匹配的部分.支持多种特殊替换模式.
  • function: 接受一些参数返回替换的值.

返回值: 一个新的字符串.

下面重点说一下newSubstr|function两个参数.

使用newSubstr作为参数

这个参数可以包括以下几个特殊的模式:

  • $$: 插入一个$.
  • $&: 插入匹配的字符串.
  • $`: 插入匹配字符串之前的字符串.
  • $': 插入匹配字符串之后的字符串.
  • $n: n是小于 100 的正整数,插入第 n 个带括号的匹配字符串,前提replace第一个参数是正则对象.

注意: $n的使用中,$1是匹配到的第一个带括号的值,$2是匹配到的字符串中第二个带括号的字符串.当需要$1匹配到整个值的话需要整个表达式加上一个()

说了那么多,可能还是云里雾里的,还是看看实际例子吧:

const SPECIAL_CHARS_REGEXP_ALL = /([:\-_]+(.))/g;
const SPECIAL_CHARS_REGEXP = /[:\-_]+(.)/g;

const str = 'user-status';

str.replace(SPECIAL_CHARS_REGEXP, '$$'); // 匹配到 '-s' return 'user$tatus'
str.replace(SPECIAL_CHARS_REGEXP_ALL, '$$'); // 匹配到 '-s' return 'user$tatus'

str.replace(SPECIAL_CHARS_REGEXP, '$&'); // 匹配到 '-s' return 'user-status'
str.replace(SPECIAL_CHARS_REGEXP_ALL, '$&'); // 匹配到 '-s' return 'user-status'

str.replace(SPECIAL_CHARS_REGEXP, '$`'); // 匹配到 '-s' return 'userusertatus'
str.replace(SPECIAL_CHARS_REGEXP_ALL, '$`'); // 匹配到 '-s' return 'userusertatus'

str.replace(SPECIAL_CHARS_REGEXP, "$'"); // 匹配到 '-s' return 'usertatustatus'
str.replace(SPECIAL_CHARS_REGEXP_ALL, "$'"); // 匹配到 '-s' return 'usertatustatus'

str.replace(SPECIAL_CHARS_REGEXP, '$1'); // 匹配到 '-s' return 'userstatus'
str.replace(SPECIAL_CHARS_REGEXP_ALL, '$1'); // 匹配到 '-s' return 'user-status'

str.replace(SPECIAL_CHARS_REGEXP, '$2'); // 匹配到 '-s' return 'user$2tatus' 是由于没有$2
str.replace(SPECIAL_CHARS_REGEXP_ALL, '$2'); // 匹配到 '-s' return 'userstatus'

str.replace(SPECIAL_CHARS_REGEXP, '$3'); // 匹配到 '-s' return 'user$3tatus', 是由于没有$3
str.replace(SPECIAL_CHARS_REGEXP_ALL, '$3'); // 匹配到 '-s' return 'user$3tatus', 是由于没有$3

使用function作为参数

你可以指定一个函数作为第二个参数,在这种情况下,该函数将在匹配完成后被调用,函数的结果(返回值)将用作替换字符串.请注意,如果第一个参数中的正则表达式是全局的,那么该函数将被多次调用.

注: 上面newSubstr的特殊替换模式不适用于这里.

函数可能接受的参数如下:

  • match: 匹配到的值,跟$&类似.
  • p1, p2, p3, ...pn: 这里可能有多个值,跟上面$n类似,p1=$1,p2=$2,没有$3因此没有p3.举个例子/(\a+)(\b+)/,那么p1就是(\a+), p2就是(\b+).
  • offset: 匹配到的字符串在整个字符串中匹配的子字符串的偏移量.比如abcd,匹配到bc,那么offset = 1.
  • string: 正在检查的整个字符串.

确切的参数数量取决于第一个参数是否是 RegExp 对象,如果是的话还要确定它指定了多少个带括号的子匹配对象.如果第一个参数是正则对象并且带有全局匹配 g,那么函数可能会被调用多次.

来个实际的例子:

const context = require.context('.', true, /\.js$/);
const obj = {};

const matchReg = /[\w_-]*(?=\.js)/gi; // (?<=./)[\w\_-]*(?=\.js)
const SPECIAL_CHARS_REGEXP = /[:\-_]+(.)/g;

const camelCase = function(name) {
	return name.replace(SPECIAL_CHARS_REGEXP, function(match, letter, offset) {
		return offset ? letter.toUpperCase() : letter;
	});
};

context.keys().forEach(function(key) {
	const matchResult = key.match(matchReg);

	if (matchResult.length !== 0 && matchResult[0] !== 'index') {
		obj[camelCase(matchResult[0])] = context(key).default
			? context(key).default
			: context(key);
	}
});

export default obj;

上面这段代码通常用作index.js,提供外部引用,因此可以随意添加子模块而不用担心忘记手动引入.而上面核心函数camelCase是将类似user-status更名为userStatus.

引用

个人随笔记录,内容不保证完全正确,若需要转载,请注明作者和出处.