我創建了一個更通用的解決方案,從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