Symbol - 看似平凡的Symbol其实我们每天都在用 - 字符串操作

470 阅读5分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

本文同时参与「掘力星计划」,赢取创作大礼包,挑战创作激励金

前言

小伙伴们大家好。前面我们分享了一篇关于对象操作的几个Symbol的内置属性。比如实例检测的Symbol.hasInstance,对象类型转换的Symbol.toPrimitive和检测数据类型的Symbol.toStringTag。这几个都是跟对象操作相关的。接下来再分享几个跟字符串操作相关的Symbol内置属性:Symbol.match、Symbol.replace、Symbol.search和Symbol.split。

Symbol.match

相信大家对String.match()这个函数或多或少都用到过,而我们平时使用时,一般会用它来匹配一个字符串或者一个正则表达式。也就是说我们在使用一般会传递一个字符串或者一个正则表达式作为match函数的参数。不知有没有小伙伴发现:当我们按住ctrl再用鼠标单击match函数后会跳转到match函数的定义,其中源码是这样的

/**
  * Matches a string or an object that supports begin matched against, and returns an array
  * containing the results of that search, or null if no matches are foung.
  * @param matcher An object that supports begin matched against.
  */
match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null;
  • 其中注释的大概意思就是:匹配一个字符串或者对象,如果匹配到了就返回一个包含了查询结果的数组,否则返回null。
  • 而从match的定义我们也能看的出:其参数matcher是一个对象,这个对象中有个[Symbol.match] (string: string)函数,返回值为数组或null。
  • 也就是说它的参数除了是我们以前常用的字符串或者正则表达式外,还可以是一个对象。对于字符串和正则表达式来说,其内部的匹配逻辑,我们是看不到的,更没办法去修改。而Symbol.match这属性就为我们开放了这个接口,让我们开发者可以自行定义内部的匹配逻辑。所以当我们给match函数传递了一个对象作为参数,并且该对象中存在[Symbol.match] (string: string)函数时,该函数的返回值将作为匹配的结果。看下面一个小栗子:
let obj = {
	[Symbol.match](str){
		return str//自定义匹配逻辑
	}
}
'hello'.match(obj);//hello
'world'.match(obj);//world

上面的代码中,我们直接将字符串返回没有做任何处理,所以结果永远都是匹配的。这样如果业务需要我们就可以在return str这里做一些我们自己的逻辑处理了。

这里我们简单演示了一下如何使用Symbol.match自定义匹配逻辑,正常开发中还需根据自己的业务需要来处理。关于Symbol.match就介绍到这里了。

Symbol.replace

Symbol.replace也是一个跟字符串操作相关的属性,从名称上看我们也应该能够猜的到,这个属性是跟字符串替换的replace函数相关的。同样我们也来看一下replace的源码定义:

/**
  * Replaces text in a string, using an object that supports replacement within a stirng.
  * @param searchValue A object can search for and replace matches within a string.
  * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
  */
replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue:string): string;

这里我们同样也看到了Symbol.replace,跟Symbol.match一样,也是为我们开放的对外接口,让我们能够实现自定义替换逻辑,这里就不再过多赘述,直接来看个小栗子吧:

let obj = {
	[Symbol.replace](searchValue, replaceValue){
		let newStr = '';
		searchValue.split(' ').forEach(item=>{
			newStr += item[0];
		})
		return newStr;
	}
}
'hello world and Javascript'.replace(obj, '');//hwaJ

上面代码我们实现了一个获取每个单词首字母并组成一个新字符串的逻辑。同match方法一样,点前面的字符串就是传给match或replace的第一个参数。掌握了这个小技巧是不是干起事来又方便了很多,想干嘛就干嘛了。

Symbol.search

接下来要说的是字符串中的search函数,该函数用于在给定的字符串中查找一个子串,并把匹配到的第一个子串的索引返回。还是先来看下源码定义

/**
  * Finds the first substring match in a regular expression in search.
  * @param searcher An object which supports searching within a string.
  */
search(searcher: { [Symbol.search](string: string):number; }): number;

这里我们看到了Symbol.search,不用想这一定也是给我们开的小灶了,这里也不多说了,直接看例子吧:

let obj = {
	[Symbol.search](str){
		return str.split(' ');
	}
}
'hello world and hello javascript'.search(obj);//['hello','world','and','hello','javascript']

上面代码实现了一个简单的将字符串以空格分隔返回一个数组的小案例,当然这只是为了展示Symbol.search的用法,并没有实际意义,反而是多次一举。实际逻辑还要根据自己的业务需要来编写。

Symbol.split

关于字符串操作的最后一个属性了。相信大家看了前面三个后,基本套路已经清晰了,无非也是针String的split函数为我们开的小灶了。

/**
  * Split a string into substrings using the specified separator and return them as an array.
  * @param spliter An object that can split a string.
  * @param limit A value used to limit the number of elements returned in the array.
  */
split(spliter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];

其用法跟前面3个是一样的,至于内部的业务逻辑可以根据情况自己随便定义,这里就不再做案例展示了。

总结

有掌握了4个新知识,原来字符串还可以这么玩。感兴趣的小伙伴快去试一下吧,今天的分享就到这里了。

喜欢的小伙伴欢迎点赞留言加关注哦!