ES6之模板字符串的使用方法

字符串模板引擎

什么是模板字符串?
ES5中的字符串缺乏多行字符串、字符串格式化、HTML转义等特性。
而ES6通过模板字面量的方式进行了填补,模板字面量试着跳出JS已有的字符串体系,通过一些全新的方法来解决问题。

1. 基本用法

ES5字符串写法:

let message = "我的宠物狗叫拆家哈士奇,今年3岁了"
console.log(message);
//输出结果:我的宠物狗叫拆家哈士奇,今年3岁了

将其转化成ES6写法,其实非常简单:
只需把最外围的双引号(")或者单引号(') 转化成反引号(`)即可。

let message = `我的宠物狗叫拆家哈士奇,今年3岁了`
console.log(message);
//输出结果:我的宠物狗叫拆家哈士奇,今年3岁了

如果想在字符串内部使用反引号,只需使用反斜杠( )转义即可

let message = `我的宠物狗叫\`拆家哈士奇\`,今年3岁了`;
console.log(message); // "我的宠物狗叫`拆家哈士奇`,今年3岁了"

2. 多行字符串

传统的JavaScript语言,输出模板通常是这样写的:

var name = '拆家哈士奇';
var age = 3;
$('#result').append(
  '我的宠物狗叫 <b>' + name + '</b>\n' +
      '今年\n' +
      '<em>' + age+ '</em>岁,\n'+
  '十分可爱!'
);

但是在ES6中,要获得同样效果的多行字符串,只需使用如下代码:

let name = '拆家哈士奇';
let age = 3;
$('#result').append(
  `我的宠物狗叫 <b>${name}</b>
      今年 
      <em>${age}</em>岁,
  十分可爱!`
);

对比两段拼接的代码,模板字符串使得我们不再需要反复使用双引号(或者单引号)了;而是改用反引号标识符(`),插入变量的时候也不需要再使用加号(+)了,而是把变量放入${ }即可。
也不用再通过写 \n 进行换行了,ES6 的模板字面量使多行字符串更易创建,因为它不需要特殊的语法,只需在想要的位置直接换行即可,此处的换行会同步出现在结果中。简单、清晰、明了。

注意:如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。因此需要特别留意缩进。

console.log(`我的宠物狗叫拆家哈士奇
                             今年3岁了`);
结果:                             
//我的宠物狗叫拆家哈士奇
//                             今年3岁了

以上代码中,模板字面量第二行前面的所有空白符都被视为字符串自身的一部分。

如果一定要通过适当的缩进来对齐文本,可以考虑在多行模板字面量的第一行空置并在后面的几行缩进

let html = `
<div>
    <h1>Title</h1>
</div>`.trim();

以上代码中,模板字面量的第一行没有任何文本,第二行才有内容。 HTML标签的缩进增强了可读性,之后再调用trim()方法移除了起始的空行。

3. 字符串中嵌入变量

模板字面量看上去仅仅是普通JS字符串的升级版,但二者之间真正的区别在于模板字面量的变量占位符。
ES5写法:

const age = 3;
const message  = '我的宠物狗叫拆家哈士奇,今年' + age*2 + '岁了' ;
//我的宠物狗叫黑子,今年6岁了

ES6写法:

const age = 3;
const message  = `我的宠物狗叫拆家哈士奇,今年 ${age*2} 岁了` ;
//我的宠物狗叫拆家哈士奇,今年6岁了

变量占位符允许将任何有效的JS表达式嵌入到模板字面量中,并将其结果输出为字符串的一部分。
如上面的例子,占位符 ${age} 会访问变量 age,并将其值插入到 message 字符串中。
既然占位符是JS表达式,还可以轻易嵌入运算符、函数调用等。

const age = 2;
const message = `我的宠物狗叫拆家哈士奇,今年 ${(age*2).toFixed(2)} 岁了`;
//"我的宠物狗叫黑子,今年 4.00 岁了"

function fn() {
  return "小黄";
}
`我朋友家的宠物叫${fn()}`
//"我朋友家的宠物叫小黄"

4. 带标签的模板字符串

要用 ES6 模板实现复杂一点的字符串处理逻辑,要依赖写函数来实现。
幸运的是,除了在模板的插值表达式里想办法调用各种字符串转换的函数之外,ES6 还提供了更加优雅且更
容易复用的方案——带标签的模板字面量(tagged template literals,以下简称标签模板)
标签模板的语法很简单,就是在模板字符串的起始反撇号前加上一个标签。
let message = tag`拆家哈士奇`;
在上面的代码中,tag就是模板标签。tag其实是一个函数,这个函数会被调用来处理这个模板字符串。

4.1 定义标签

let  name = '拆家哈士奇',
     age = 2,
     message = tag`我的宠物狗叫${name},今年${age}岁了`;

function tag(stringArr, value1, value2) {
    console.log(stringArr);  //["我的宠物狗叫", ",今年", "岁了", raw: Array(3)]
                             //该数组有一个raw属性,保存的是转义后的原字符串
    console.log(value1);     // 拆家哈士奇
    console.log(value2);     // 2
    return;
}
标签函数通常使用不定参数特性来定义占位符,从而简化数据处理的过程

function tag(stringArr, ...values) {
     console.log(values); //  ["拆家哈士奇", 2]
}

4.2 实际应用

“标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容

var message =  filterHTML`<p>${sender} 你好啊</p>`;
function filterHTML(templateData) {
  var s = templateData[0];
  for (var i = 1; i < arguments.length; i++) {
    var arg = String(arguments[i]);
    // 转义占位符中的特殊字符。
    s += arg.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");
    // 不转义模板中的特殊字符。
    s += templateData[i];
  }
  return s;
}

上面代码中,sender变量往往是用户提供的,经过filterHTML函数处理,里面的特殊字符都会被转义。

var sender = '<script>alert("买了个包")</script>'; // 恶意代码
var message = filterHTML`<p>${sender} 你好啊</p>`;

console.log(message);
// <p>&lt;script&gt;alert("买了个包")&lt;/script&gt;  你好啊</p>

即使一个恶意命名的用户,例如黑客向其他用户发送一条骚扰信息,无论如何这条信息都会被转义为普通字符串,
其他用户不会受到潜在攻击的威胁。
标签模板的另一个应用,就是多语言转换(国际化处理)

let name = 'ES6专栏 ';  let  number = 666;  
let chinese = ['欢迎访问','您是第','位访问者'];

i18n`Welcome to ${name}, you are the ${number}  visitor`;  

function i18n(stringArr, ...values){
    let str='';  
    stringArr.map((item,index)=>{
        str += (chinese[index] +  (values[index] ? values[index] : '' ))   
    });
    console.log(str) 
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容