冷知識:不起眼但有用的String.raw方法
String.raw
String.raw
是JavaScript中模板字符串的一個標籤函數,它的作用是將模板字符串不轉義的原始字符串內容返回。
也就是説,如下代碼:
js
console.log(String.raw`Hi!\nAkira`);
將直接返回字符串 Hi!\nAkira
,而不是在Hi!
和Akira
中間插入回車。因為String.raw標籤存在,所以\n
不被轉義。這樣其實相當於如下代碼:
js
console.log(`Hi!\\nAkira`);
原始字符串不轉義,在某些情況下很有用。不知道大家有沒有遇到過用new RegExp
動態構建正則表達式的場景,比如下面的代碼構建一個瀏覽器默認塊級元素標籤的正則匹配:
```js const blockTags = 'address|article|aside|base|basefont|blockquote|body|caption' + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + '|track|ul';
const blockReg = new RegExp((<\\s*(?:(?:\\/\\s*(?:${blockTags})\\s*)|(?:(?:${blockTags})\\s*\\/\\s*)|hr)>\\s*?)\\n
, 'ig');
```
在這裏,因為我們使用了new RegExp
動態構建,所以我們就要把\s
替換成\\s
,把\/
替換成\\/
,把\n
替換成\\n
。但如果使用String.raw
,就可以不用這麼替換,可以直接寫成:
js
const blockReg = new RegExp(String.raw`(<\s*(?:(?:\/\s*(?:${blockTags})\s*)|(?:(?:${blockTags})\s*\/\s*)|hr)>\s*?)\n`, 'ig');
除了動態構建正則,還有輸出或執行代碼塊的場景,比如:
js
const script = `
console.log('test \n test');
`
execScript(script);
上面這段代碼執行會出錯,因為\n
在字符串字面量中被替換成換行,導致實際執行的代碼變成下面這樣:
js
console.log('test
test');
因為單引號字符串裏面不能插入換行,所以上面的代碼執行就報錯了。
解決的辦法是:
js
const script = String.raw`
console.log('test \n test');
`
execScript(script);
這樣就可以避免字符串代碼的轉義內容被解析。
所以,從上面可以看出,在字符串解析的場景下,String.raw
就會有用。比如我們要寫一個使用KaTeX解析公式的React組件,我們希望這麼使用:
html
<Katex macros={{...}}>
公式字符串
</Katex>
具體實現我們可以這樣寫:
```js import katex from 'katex'; import React from 'react'; import ReactDOM from 'react-dom';
const Katex = ({children, ...props}) => { const code = katex.renderToString(children, { ...props, throwOnError: false }) return ( ) } ```
對於單行公式的解析沒有問題
html
<Katex>x^2+y^2=1</Katex>
能夠正確解析成:$x^2+y^2=1$
但是如果是多行公式:
jsx
<Katex macros={{"\\f": "#1f(#2)"}}>
% \f is defined as #1f(#2) using the macro
\f\relax{x} = \int_{-\infty}^\infty
\f\hat\xi\,e^{2 \pi i \xi x}
\,d\xi
</Katex>
這麼寫是不行的,因為React在解析JSX的時候,會把內容中的回車去掉,空格合併,就像瀏覽器解析HTML標籤那樣,而且也不能正確處理轉義符。所以如果像上面這麼寫,最後瀏覽器會報錯。
這時候,我們就可以使用String.raw標籤,將上面的代碼寫成下面這樣:
jsx
<Katex macros={{"\\f": "#1f(#2)"}}>{String.raw`
% \f is defined as #1f(#2) using the macro
\f\relax{x} = \int_{-\infty}^\infty
\f\hat\xi\,e^{2 \pi i \xi x}
\,d\xi
`}</Katex>
這樣KaTeX就能正確解析字符串內容了,最終實現效果如下:
http://code.juejin.cn/pen/7106683225786810376
自定義標籤
除了默認的String.raw,我們自定義的標籤函數,也可以通過strings.raw來獲得原始字符串內容,所以我們也可以將KaTeX公式解析定義成標籤函數:
js
function KaTeX(strings, macros) {
return katex.renderToString(strings.raw.join(''), {
macros,
throwOnError: false
});
}
這樣我們就可以通過標籤函數來解析公式,再用React渲染出來:
http://code.juejin.cn/pen/7106726810817462286
以上就是全部內容,雖然很簡單,但是非常有用。
你還知道或用過String.raw
以及其他標籤函數嗎?歡迎在評論區討論。
- Day1:用原生JS把你的設備變成一台架子鼓!
- 【零基礎】充分理解WebGL(七)
- 【零基礎】充分理解WebGL(六)
- 【零基礎】充分理解WebGL(五)
- 冷知識:不起眼但有用的String.raw方法
- 【零基礎】充分理解WebGL(四)
- 【零基礎】充分理解WebGL(三)
- 【零基礎】充分理解WebGL(二)
- 【零基礎】充分理解WebGL(一)
- css-doodle:如何讓CSS成為藝術?
- 創建合輯,將【碼上掘金】作為開源項目的demo庫使用
- 使用 babel 插件來打造真正的“私有”屬性
- 使用 Node.js 對文本內容分詞和關鍵詞抽取
- 用信號來控制異步流程
- 設計 Timeline 時間軸來更精確地控制動畫
- 簡單構建 ThinkJS Vue2.0 前後端分離的多頁應用
- 冷門函數之Math.hypot
- 你還在用charCodeAt那你就out了
- 巧用 currentColor 屬性來實現自定義 checkbox 樣式
- 在什麼情況下 a === a - 1 ?