摘要:最終的代碼如下第二版假設(shè)有這樣一段為了保持可讀性,我希望最終輸入的樣式為其實(shí)就是匹配每行前面的空格,然后將其替換為空字符串。
基礎(chǔ)用法
let message = `Hello World`; console.log(message);
如果你碰巧要在字符串中使用反撇號(hào),你可以使用反斜杠轉(zhuǎn)義:
let message = `Hello ` World`; console.log(message);
值得一提的是,在模板字符串中,空格、縮進(jìn)、換行都會(huì)被保留:
let message = `
注意,打印的結(jié)果中第一行是一個(gè)換行,你可以使用 trim 函數(shù)消除換行:
let message = `
模板字符串支持嵌入變量,只需要將變量名寫在 ${} 之中,其實(shí)不止變量,任意的 JavaScript 表達(dá)式都是可以的:
let x = 1, y = 2; let message = `
值得一提的是,模板字符串支持嵌套:
let arr = [{value: 1}, {value: 2}]; let message = `
打印結(jié)果如下:
注意,在 li 標(biāo)簽中間多了一個(gè)逗號(hào),這是因?yàn)楫?dāng)大括號(hào)中的值不是字符串時(shí),會(huì)將其轉(zhuǎn)為字符串,比如一個(gè)數(shù)組 [1, 2, 3] 就會(huì)被轉(zhuǎn)為 1,2,3,逗號(hào)就是這樣產(chǎn)生的。
如果你要消除這個(gè)逗號(hào),你可以先 join 一下:
let arr = [{value: 1}, {value: 2}]; let message = `
打印結(jié)果如下:
標(biāo)簽?zāi)0?/b>模板標(biāo)簽是一個(gè)非常重要的能力,模板字符串可以緊跟在一個(gè)函數(shù)名后面,該函數(shù)將被調(diào)用來(lái)處理這個(gè)模板字符串,舉個(gè)例子:
let x = "Hi", y = "Kevin"; var res = message`${x}, I am ${y}`; console.log(res);
我們可以自定義 message 函數(shù)來(lái)處理返回的字符串:
// literals 文字 // 注意在這個(gè)例子中 literals 的第一個(gè)元素和最后一個(gè)元素都是空字符串 function message(literals, value1, value2) { console.log(literals); // [ "", ", I am ", "" ] console.log(value1); // Hi console.log(value2); // Kevin }
我們利用這些參數(shù)將其拼合回去:
function message(literals, ...values) { let result = ""; for (let i = 0; i < values.length; i++) { result += literals[i]; result += values[i]; } result += literals[literals.length - 1]; return result; }
你也可以這樣寫:
function message(literals, ...values) { let result = literals.reduce((prev, next, i) => { let value = values[i - 1]; return prev + value + next; }); return result; }
學(xué)著拼合回去是一件非常重要的事情,因?yàn)槲覀兘?jīng)過(guò)各種處理,最終都還是要拼回去的……
oneLine講完了基礎(chǔ),我們可以來(lái)看一些實(shí)際的需求:
let message = ` Hi, Daisy! I am Kevin. `;
出于可讀性或者其他原因,我希望書寫的時(shí)候是換行的,但是最終輸出的字符是在一行,這就需要借助模板標(biāo)簽來(lái)實(shí)現(xiàn)了,我們嘗試寫一個(gè)這樣的函數(shù):
// oneLine 第一版 function oneLine(template, ...expressions) { let result = template.reduce((prev, next, i) => { let expression = expressions[i - 1]; return prev + expression + next; }); result = result.replace(/(s+)/g, " "); result = result.trim(); return result; }
實(shí)現(xiàn)原理很簡(jiǎn)單,拼合回去然后將多個(gè)空白符如換行符、空格等替換成一個(gè)空格。
使用如下:
let message = oneLine ` Hi, Daisy! I am Kevin. `; console.log(message); // Hi, Daisy! I am Kevin.
不過(guò)你再用下去就會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,如果字符間就包括多個(gè)空格呢?舉個(gè)例子:
let message = oneLine` Preserve eg sentences. Double spaces within input lines. `;
如果使用這種匹配方式,sentences. 與 Double 之間的兩個(gè)空格也會(huì)被替換成一個(gè)空格。
我們可以再優(yōu)化一下,我們想要的效果是將每行前面的多個(gè)空格替換成一個(gè)空格,其實(shí)應(yīng)該匹配的是換行符以及換行符后面的多個(gè)空格,然后將其替換成一個(gè)空格,我們可以將正則改成:
result = result.replace(/( s*)/g, " ");
就可以正確的匹配代碼。最終的代碼如下:
// oneLine 第二版 function oneLine(template, ...expressions) { let result = template.reduce((prev, next, i) => { let expression = expressions[i - 1]; return prev + expression + next; }); result = result.replace(/( s*)/g, " "); result = result.trim(); return result; }stripIndents
假設(shè)有這樣一段 HTML:
let html = `
1
2
3
`;
為了保持可讀性,我希望最終輸入的樣式為:
1
2
3
其實(shí)就是匹配每行前面的空格,然后將其替換為空字符串。
// stripIndents 第一版 function stripIndents(template, ...expressions) { let result = template.reduce((prev, next, i) => { let expression = expressions[i - 1]; return prev + expression + next; }); result = result.replace(/ [^S ]*/g, " "); result = result.trim(); return result; }
最難的或許就是這個(gè)正則表達(dá)式了:
result = result.replace(/ [^S ]*/g, " ");
S 表示匹配一個(gè)非空白字符
[^S ] 表示匹配非空白字符和換行符之外的字符,其實(shí)也就是空白字符去除換行符
[^S ]* 表示匹配換行符以及換行符后的多個(gè)不包含換行符的空白字符
replace(/ [^S ]*/g, " ") 表示將一個(gè)換行符以及換行符后的多個(gè)不包含換行符的空白字符替換成一個(gè)換行符,其實(shí)也就是將換行符后面的空白字符消掉的意思
其實(shí)吧,不用寫的這么麻煩,我們還可以這樣寫:
result = result.replace(/^[^S ]+/gm, "");
看似簡(jiǎn)單了一點(diǎn),之所以能這樣寫,是因?yàn)槠ヅ淠J降木壒剩銜?huì)發(fā)現(xiàn),這次除了匹配全局之外,這次我們還匹配了多行,m 標(biāo)志用于指定多行輸入字符串時(shí)應(yīng)該被視為多個(gè)行,而且如果使用 m 標(biāo)志,^ 和 $ 匹配的開(kāi)始或結(jié)束是輸入字符串中的每一行,而不是整個(gè)字符串的開(kāi)始或結(jié)束。
1 表示匹配空白字符去除換行符
^2+ 表示匹配以去除換行符的空白字符為開(kāi)頭的一個(gè)或者多個(gè)字符
result.replace(/^3+/gm, "") 表示將每行開(kāi)頭一個(gè)或多個(gè)去除換行符的空白字符替換成空字符串,也同樣達(dá)到了目的。
最終的代碼如下:
// stripIndents 第二版 function stripIndents(template, ...expressions) { let result = template.reduce((prev, next, i) => { let expression = expressions[i - 1]; return prev + expression + next; }); result = result.replace(/^[^S ]+/gm, ""); result = result.trim(); return result; }stripIndent
注意,這次的 stripIndent 相比上面一節(jié)的標(biāo)題少了一個(gè)字母 s,而我們想要實(shí)現(xiàn)的功能是:
let html = `
其實(shí)也就是去除第一行的換行以及每一行的部分縮進(jìn)。
這個(gè)實(shí)現(xiàn)就稍微麻煩了一點(diǎn),因?yàn)槲覀円?jì)算出每一行到底要去除多少個(gè)空白字符。
實(shí)現(xiàn)的思路如下:
使用 match 函數(shù),匹配每一行的空白字符,得到一個(gè)包含每一行空白字符的數(shù)組
數(shù)組遍歷比較,得到最小的空白字符長(zhǎng)度
構(gòu)建一個(gè)正則表達(dá)式,然后每一行都替換掉最小長(zhǎng)度的空白字符
實(shí)現(xiàn)的代碼如下:
let html = `
值得一提的是,我們一般會(huì)以為正則中 . 表示匹配任意字符,其實(shí)是匹配除換行符之外的任何單個(gè)字符。
最終精簡(jiǎn)的代碼如下:
function stripIndent(template, ...expressions) { let result = template.reduce((prev, next, i) => { let expression = expressions[i - 1]; return prev + expression + next; }); const match = result.match(/^[^S ]*(?=S)/gm); const indent = match && Math.min(...match.map(el => el.length)); if (indent) { const regexp = new RegExp(`^.{${indent}}`, "gm"); result = result.replace(regexp, ""); } result = result.trim(); return result; }includeArrays
前面我們講到為了避免 ${} 表達(dá)式中返回一個(gè)數(shù)組,自動(dòng)轉(zhuǎn)換會(huì)導(dǎo)致多個(gè)逗號(hào)的問(wèn)題,需要每次都將數(shù)組最后再 join("") 一下,再看一遍例子:
let arr = [{value: 1}, {value: 2}]; let message = `
利用標(biāo)簽?zāi)0澹覀兛梢暂p松的解決這個(gè)問(wèn)題:
function includeArrays(template, ...expressions) { let result = template.reduce((prev, next, i) => { let expression = expressions[i - 1]; if (Array.isArray(expression)) { expression = expression.join(""); } return prev + expression + next; }); result = result.trim(); return result; }最后
你會(huì)發(fā)現(xiàn)以上這些函數(shù)拼合的部分都是重復(fù)的,我們完全可以將其封裝在一起,根據(jù)不同的配置實(shí)現(xiàn)不能的功能。如果你想在項(xiàng)目中使用這些函數(shù),可以自己封裝一個(gè)或者直接使用 common-tags。
ES6 系列ES6 系列目錄地址:https://github.com/mqyqingfen...。
ES6 系列預(yù)計(jì)寫二十篇左右,旨在加深 ES6 部分知識(shí)點(diǎn)的理解,重點(diǎn)講解塊級(jí)作用域、標(biāo)簽?zāi)0濉⒓^函數(shù)、Symbol、Set、Map 以及 Promise 的模擬實(shí)現(xiàn)、模塊加載方案、異步處理等內(nèi)容。
如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑?qǐng)務(wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎star,對(duì)作者也是一種鼓勵(lì)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/107826.html
摘要:前言這里的泛指之后的新語(yǔ)法這里的完全是指本文會(huì)不斷更新這里的使用是指本文會(huì)展示很多的使用場(chǎng)景這里的手冊(cè)是指你可以參照本文將項(xiàng)目更多的重構(gòu)為語(yǔ)法此外還要注意這里不一定就是正式進(jìn)入規(guī)范的語(yǔ)法。 前言 這里的 ES6 泛指 ES5 之后的新語(yǔ)法 這里的 完全 是指本文會(huì)不斷更新 這里的 使用 是指本文會(huì)展示很多 ES6 的使用場(chǎng)景 這里的 手冊(cè) 是指你可以參照本文將項(xiàng)目更多的重構(gòu)為 ES6...
摘要:所以它與其他系列的文章并不沖突,完全可以在閱讀完這個(gè)系列后,再跟著其他系列的文章接著學(xué)習(xí)。如何閱讀我在寫系列的時(shí)候,被問(wèn)的最多的問(wèn)題就是該怎么閱讀源碼我想簡(jiǎn)單聊一下自己的思路。感謝大家的閱讀和支持,我是冴羽,下個(gè)系列再見(jiàn)啦 前言 別名:《underscore 系列 8 篇正式完結(jié)!》 介紹 underscore 系列是我寫的第三個(gè)系列,前兩個(gè)系列分別是 JavaScript 深入系列、...
摘要:為我們提供了模板字符串,語(yǔ)法使用反引號(hào)。模板字符串具有以下三個(gè)優(yōu)點(diǎn)多行文本字符串中插入變量字符串中插入表達(dá)式基本語(yǔ)法模板字符串和的字符串的聲明一樣。總結(jié)模板字符串就是這么的簡(jiǎn)單這么的好用。 ES6為我們提供了模板字符串,語(yǔ)法使用反引號(hào)`。模板字符串具有以下三個(gè)優(yōu)點(diǎn): 多行文本 字符串中插入變量 字符串中插入表達(dá)式 基本語(yǔ)法 模板字符串和 ES5的字符串的聲明一樣。 // ES5 v...
摘要:由兩部分組成模板起始符,稱為沉音符反引號(hào),其內(nèi)容被識(shí)別為字符串模板。其實(shí)這是通過(guò)屬性操作中的結(jié)果,也就是說(shuō)屬性將對(duì)控制符進(jìn)行轉(zhuǎn)義從而實(shí)現(xiàn)按照普通字符輸出。的語(yǔ)法是緊跟在后面,兩者間不能有空格或制表符等。 1. Brief ES6(ECMAScript 6th edition)于2015年7月份發(fā)布,雖然各大瀏覽器仍未全面支持ES6,但我們可以在后端通過(guò)Node.js 0.12和io....
摘要:模板字符串連接符在之前,將字符串連接到一起的舊方法是使用字符串連接運(yùn)算符。這樣更容易構(gòu)建字符串。返回布爾值,表示參數(shù)字符串是否在原字符串的頭部。它針對(duì)前個(gè)字符,而其他兩個(gè)方法針對(duì)從第個(gè)位置直到字符串結(jié)束。 模板字符串 + 連接符 在 ES6 之前,將字符串連接到一起的舊方法是使用字符串連接運(yùn)算符 (+)。 const student = { name: Richard Kaleho...
閱讀 2311·2021-11-23 09:51
閱讀 3748·2021-11-11 10:57
閱讀 1391·2021-10-09 09:43
閱讀 2481·2021-09-29 09:35
閱讀 2013·2019-08-30 15:54
閱讀 1788·2019-08-30 15:44
閱讀 3179·2019-08-30 13:20
閱讀 1687·2019-08-30 11:19