我创建了一个更通用的解决方案,从emojis到相关名称的映射开始。需要被保持同步,而不是两个名单,我用一个单独的对象:
const emojis = {
'(c)': 'a9',
'(r)': 'ae',
'(tm)': '2122'
//, ...
};
这令我更加有用的结构与工作,但下面的代码可以很容易地被改变,以应对双列表版本。
然后我使用一个辅助功能,通过与\
前面加上他们逃离这是不允许的正则表达式中明文字符:
const escapeSpecials = (() => {
const specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
const reg = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
return str => str.replace(reg, '\\$1');
})();
然后,我有钥匙功能:
const replaceStringsWith = (emojis, convert) => str => Object.keys(emojis).reduce(
(str, em) => str.replace(new RegExp(`(^|\\s+)(${escapeSpecials(em)})($|\\s+)`, 'g'),
(m, a, b, c) => `${a}${convert(emojis[b], b)}${c}`),
str
);
这需要一个包含字符串/替换对的对象和一个接受替换的转换器函数,并返回最终形式。它返回一个函数,该函数接受一个字符串,然后搜索该对象关键字上的任何匹配(正确检查字符串或字符串结尾),将其替换为针对特定键的对象值调用转换器的结果。
因此,我们可以这样做:
const toUrl = (name) => `<img src='http://abs.twimg.com/emoji/v1/72x72/${name}.png'>`;
const replaceEmojis = replaceStringsWith(emojis, toUrl)
,并把它作为
const s = "This is Copyright (c) 2017, FooBar is (tm) BazCo (r)";
replaceEmojis(s); //=>
// `This is Copyright <img src='http://abs.twimg.com/emoji/v1/72x72/a9.png'>
// 2017, FooBar is <img src='http://abs.twimg.com/emoji/v1/72x72/2122.png'>
// BazCo <img src='http://abs.twimg.com/emoji/v1/72x72/ae.png'>`
注意,转换器还需要第二个参数。所以,你可以改用
const toUrl = (name, emoji) =>
`<img src='http://abs.twimg.com/emoji/v1/72x72/${name}.png' title='${emoji}'>`;
得到
//=> `This is Copyright <img
// src='http://abs.twimg.com/emoji/v1/72x72/a9.png' title='(c)'>
// 2017, FooBar is <img src='http://abs.twimg.com/emoji/v1/72x72/2122.png'
// title='(tm)'> BazCo <img src='http://abs.twimg.com/emoji/v1/72x72/ae.png' title='(r)'>"
首先,它不是一个好主意,用'for..in'上的对象 – Rajesh
@Rajesh为什么它的循环一样'(VAR我= 0; ......)' –
'for..in'是为了循环对象的属性。因此,在旧的浏览器,'for..in'还会遍历'.length'财产 – Rajesh