文档章节

ES6 Features系列:Template Strings & Tagged Template Strings

我爱睡觉
 我爱睡觉
发布于 2017/06/24 17:41
字数 1571
阅读 4
收藏 0

1. Brief

  ES6(ECMAScript 6th edition)于2015年7月份发布,虽然各大浏览器仍未全面支持ES6,但我们可以在后端通过Node.js 0.12和io.js,而前端则通过Traceur或Babel这类Transpiler将ES6语法预转译为ES5语法,来提前兴奋一把。而仅需适配IE9+的朋友们现在更是可以开始撸ES6了,而不必为学哪门JavaScript超集语言而烦恼。(ES6又名为ECMAScript 2015或JavaScript.next,ES4的部分较为激进的特性被调用到该版本中实现。)

  ES6带给我们很多惊喜,如class、module、export和import等。但在学习和运用到项目中时,我们需要注意以下两点:

  1. ES6包含的是语法糖和语言、库的bug fix,对工程性问题没有太大的帮助;

  2. 由于Traceur和Babel无法对ES6的所有特性进行完整高效的polyfill,因此我们无法完全享用ES6的各项特性。

  最近接手一个项目的前端改造,正在尝试全新的技术栈(Riot+ES6+Glup+Webpack),本系列文章将作为理论+项目实践的笔记供日后查阅。

 

2. What is Template Strings?

  一言以蔽之,Template Strings就是让我们减少字符串手工拼接的工作量。

  2.1. Before ES6

// Sample 1: 单行字符串拼接
var operand1 = 1
  , operand2 = 2.1
var tpl1 = operand1 + ' + ' + operand2 + '~=' + parseInt(operand1+operand2)
var tpl2 = [operand1, ' + ' , operand2, '~=', parseInt(operand1 + operand2)].join('')
// Sample 2: 多行字符串拼接
var name = 'fsjohnhuang'
  , id = 'region'
var tpl1 = '<div id="' + id + '">'
  + '<a>' + name + '</a>'
  + '</div>'
var tpl2 = '<div id=" ' + id + ' ">\
  <a>' + name + '</a>\
  </div>'

  2.2. Embracing ES6

// Sample 1: 单行字符串拼接
var operand1 = 1
  , operand2 = 2.1
var tpl1 = `${operand1}+${operand2}~=${parseInt(operand1+operand2)}`
// Sample 2: 多行字符串拼接
var name = 'fsjohnhuang'
  , id = 'region'
var tpl1 = `<div id="${id}">
  <a>${name}</a>
  </div>`

  假若了解过CoffeeScript,那么会发现ES6的Template Strings怎么这么眼熟。Template Strings由两部分组成:

    1. 模板起始符—— `` ,称为沉音符/反引号(grave accent),其内容被识别为字符串模板。

    2. 表达式占位符—— ${<expression>} ,<expression>为JavaScript的有效表达式(如 name, 1==2等),因此 ${<expression>} 并不是简单的占位符那么简单了。

  2.3. Cautions

    1.  ${<expression>} 中可访问当前作用域所能访问到变量和函数,如

var x = 1

(function(){
  var y = 2
  (function(b){
    var tpl = `${x},${y},${a},${b}` // 结果是 "1,2,undefined,5"
  }(5))
  var a = 3
  let c = 4 // 由于采用let来声明c变量,因此不会发生variable hoist
}())

    2.  ${<expression>} 是即时计算(real-time computing)的,通过函数加壳可实现延迟计算(lazy evaluation)

//real-time computing
var tpl = `${x},${y}`
var x = 1, y = 2
console.log(tpl) // "undefined, undefined"

// lazy evaluation
var tpl = ctx => `${ctx.x},${ctx.y}`
console.log(tpl({x:1, y:2})) // "1, 2"

   3. 多行陷阱(pitfall of multiline),在编写HTML模板时我习惯如下写法

var tpl = '<div>\
    <h3>${title}</h3>\
    <span>${subtitle}</span>\
  </div>'
// 然后是模板引擎解析tpl

   那现在是否就可以毫无顾虑地改用Template Strings呢?

var tpl = ctx => `<div>
    <h3>${ctx.title}</h3>
    <span>${ctx.subtitle}</span>
  </div>`
// 直接调用tpl函数

   答案是否定的

   原因是通过正斜杠( \ )定义的多行字符串实际输出还是一行字符串而已,但通过反引号( `` )定义的是真实的多行字符串,且通过换行符( \n )分隔每一行。

// 通过\定义多行的结果
<div>    <h3>${ctx.title}</h3>    <span>${ctx.subtitle}</span>  </div>


// 通过反引号定义多行的结果
<div>\n
    <h3>${ctx.title}</h3>\n
    <span>${ctx.subtitle}</span>\n
  </div>

  那么当使用jQuery将反引号定义的HTML模板来生产DOM元素时就会直接报错了,这时我们需要删除这些控制字符。

var removeCtlChar = raw => raw.replace(/[\r\n\t\v\f]/ig, '')

 

3. What is Tagged Template Strings?

  从上文我们了解到Template Strings是以整体为单位进行即时计算,也就是说留给我们的自主操控能力是十分有限的。而Tagged Template Strings则大大增强了我们的操控欲望。

  其实Tagged Template Strings实质上是对Template Strings进行Tokenize操作,从而细化我们的可操作粒度。而词法类型分为 字符串表达式占位符的运算结果

var x = 1, y = 2
var tpl = 'hello${x}:${y+1}'

// Tokenize后的结果
var tokens = ['hello', 1, ':', 3, '']

   具体玩法如下:

// 语法
<Tagged Function><Template Strings>

/** Sample **/
/* 定义<Tagged Function>
 * @param {Array.<DOMString>} strings - 字符串类型的tokens
 * @param {...Any} vals - 表达式占位符的运算结果tokens
 * @returns {Any}
 */
var taggedFunc = (strings, ...vals){
  var ret = []
  for(let i = 0, len = strings.length ; i < len; ++i)
    ret.push(strings.raw[i], vals[i] || '')
  return ret
}

// 定义Template Strings
var x = 1, y =2
var ret = taggedFunc`\tHello${x}:${y+1}`
console.log(ret) // 显示 "\tHello1:3"
console.log(`\tHello${x}:${y+1}`) // 显示 "    Hello1:3"

   <Tagged Function>函数 有两个入参分别代表两类token。 {Array.<DOMString>} strings 为字符串类型的tokens,而 {...Any} vals 则为表达式占位符运算结果tokens。

   而需要注意的是: strings.length === vals.length + 1 

   另外我们看到最后两行代码会发现 `\tHello${x}:${y+1}` 中的制表符将在输出结果中起效,而经过Tagged Function处理的则按普通字符输出而已。其实这是通过 {Array.<DOMString>}strings.raw属性 操作strings中token的结果,也就是说strings.raw属性将对控制符进行转义从而实现按照普通字符输出。

   3.1. 内置的Tagged Function——String.raw

     其作用与上述的taggedFunc一样,就是将按普通字符输出Template Strings中的控制符。

   3.2. Cautions

     1. Tagge Template Strings的语法是Template Strings紧跟在Tagged Function后面,两者间不能有空格或制表符等。

     2. vals是运算后的实际值,若要延迟计算依然需要加壳。

     3. @ruanyifeng老师说可通过Tagged Function来自定义带流程控制的模板语言

// 下面的hashTemplate函数
// 是一个自定义的模板处理函数
var libraryHtml = hashTemplate`
  <ul>
    #for book in ${myBooks}
      <li><i>#{book.title}</i> by #{book.author}</li>
    #end
  </ul>
`;

        本人觉得这种用法不可取,Tagged Function本来就按照自身规则对模板进行Tokenize,然后我们在此基础上对结果进行二次Tokenize,那还不如直接按自己定义的规则来做词法分析更省心。

 

4. Conclusion

   Template Strings和Tagged Template Strings 均可通过Traceur和Babel做transpile,所以我们现在就可以撸起了,开干吧各位!

   尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/4601200.html  肥子John^_^

 

5. Thanks

    http://es6.ruanyifeng.com/#docs/string

    http://www.sitepoint.com/understanding-ecmascript-6-template-strings/

本文转载自:http://www.cnblogs.com/fsjohnhuang/p/4601200.html

我爱睡觉
粉丝 3
博文 2120
码字总数 0
作品 0
南昌
私信 提问
ES6 new syntax features

Fat arrow function syntax fat arrow 即: '=>' 通常我们在调用一个方法里带有一个function作为参数时我们一般这样用: 现在我们可以使用这种 fat arrow "=>" ,于是上面科一这样写: 另一个...

Mercy_丶
2016/05/24
22
0
es6 模板字符串

es6 新的特殊支持嵌入表达式,自动会处于内所有的字符串。 多行字符串 表达式插入 传统的方式采用的是字符串拼接的方式进行,通过+号进行拼接 带标签的模板字符串 通过传入的参数来返回一个函...

罗布V
2016/11/01
2
0
Vue.js 1.0.17 发布,轻量级 JavaScript 框架

Vue.js 1.0.17 发布,更新如下: New v-for now also supports using of as the delimiter: The internal transition API is now exposed on Vue.transition. For example this function wil......

limichange
2016/02/29
2.4K
15
Python标准库-string模块《未完待续》

>>> import string >>> s='hello rollen , how are you '>>> string.capwords(s)'Hello Rollen , How Are You' #每个单词的首字母大写>>> string.split(s)['hello', 'rollen', ',', 'how', ......

泳泳啊泳泳
2017/12/26
0
0
Domplate

Overview The Domplate jquery plugin provides an advanced template system taken and modified from Firebug. Features: Templates are assembled via function calls instead of strings......

匿名
2008/09/19
381
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot源码:启动过程分析(二)

接着上篇继续分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 一样的,我们先把时序图贴上来,方便理解: 二.源码分析 回顾一下,前面我们分析到了下...

Jacktanger
昨天
0
0
Apache防盗链配置,Directory访问控制,FilesMatch进行访问控制

防盗链配置 通过限制referer来实现防盗链的功能 配置前,使用curl -e 指定referer [root@test-a test-webroot]# curl -e "http://www.test.com/1.html" -x127.0.0.1:80 "www.test.com/1.jpg......

野雪球
昨天
2
0
RxJava threading

因为Rx针对异步系统设计,并且Rx也自然支持多线程,所以新的Rx开发人员有时会假设Rx默认是多线程的。在其他任何事情之前,重要的是澄清Rx默认是单线程的。 除非另有说明,否则每次调用onNex...

woshixin
昨天
0
0
Python的安装及文件类型、变量

一、为什么学习python 服务于大数据、人工智能、自动化运维。 简单易学 代码简洁 薪资高 近几年越来越火 二、Python的安装 linux 系统默认安装, CentOS7 默认安装了python2.7 安装ipython y...

枫叶云
昨天
1
0
JeeSite 4.x 树形结构的表设计和用法

有些同仁对于 JeeSite 4 中的树表设计不太了解,本应简单的方法就可实现,却写了很多复杂的语句和代码,所以有了这篇文章。 在 JeeSite 4 中的树表设计我还是相对满意的,这种设计比较容易理...

ThinkGem
昨天
29
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部