• ES6类型扩展模板字面量


    JS的字符串的功能一直以来都特别有限,缺乏很多特性,比如不能直接表示多行字符串、字符串格式化、HTML转义等等。ES6通过模板字面量方式进行了填补,它通过全新的方法解决了这些问题。

    基础用法

    模板字面量使用反引号``标识。

    let s = `hello world`
    console.log(s) // 'hello world'
    
    // 如果字符串中想要包含反引号,需要使用反斜杠(\)转义
    let s2 = `\`hello world\``
    console.log(s2) // '`hello world`'
    

    多行字符串

    在ES6之前,要想表示多行字符串,开发者通常需要手动加入\n换行符。
    JavaScript有一个语法bug,在换行符后面添加反斜杠,可以承接下一行的代码,虽然也起到了换行的作用,但不建议这么做。

    let s = 'hello \n'
    +'world'
    console.log(s)
    // 'hello'
    // 'world'
    
    
    let s2 = 'hello \n\
    world'
    console.log(s2)
    // 'hello'
    // 'world'
    

    使用模板字面量可以轻松创建多行字符串,反引号内的空白符会作为字符串的一部分。

    let s = `hello
    world`
    
    console.log(s)
    // 'hello'
    // 'world'
    
    
    let s1 = `hello
        world`
    console.log(s1)
    // hello
    //    world
    

    由于空白符会作为字符串的一部分,所以通过缩进对齐文本时,第一行可以留空,然后缩进后面的内容。

    let s = `
    <p>
      <span>hello world</span>
    </p>`.trim()
    
    console.log(s)
    // <p>
    //   <span>hello world</span>
    // </p>
    

    变量占位符

    变量占位符允许将任何有效的JS表达式嵌入到模板字面量中,并将其结果输出为字符串的一部分。变量占位符用${}表示。

    let s = 'hello', n = 1.3;
    function fn() {
      return 'world'
    }
    
    console.log(`${s} ${fn()} ${Math.cell(n)}`)
    // 'hello world 2'
    

    模板字面量可以嵌入到另一个模板字面量内部

    let s = 'world'
    console.log(`hello ${`${s}!`}`)
    
    // 'hello world!'
    

    标签模板

    标签模板可以说是模板字面量最强大的地方。标签指的是模板字面量第一个反引号前面标注的字符串,模板就是两个反引号之间的部分。

    let s = tag`Hello world`
    

    tag是应用到Hello world模板字面量上的标签

    定义标签

    标签可以是一个函数:函数的第一个参数是数组,包含了模板字面量中的原始字符串;其他参数是每一个占位符的解释值。

    let name = 'Xiaowang', country = 'China'
    let s = tag`My name is ${name}, I am from ${country}`
    

    如果有一个tag函数做为模板字面量的标签,那么它会接收3个参数:

    1. 第一个参数是数组,包含了3个原始字符串,即['My name is', ', I am from', '']
    2. 第二个参数是变量name的解释值,即Xiaowang
    3. 第三个参数是变量country的解释值,即China
    let name = 'Xiaowang', country = 'China'
    let s = tag`My name is ${name}, I am from ${country}`
    
    // 等价于
    let s = tag(['My name is', ', I am from', ''], 'Xiaowang', 'China')
    

    标签函数通常使用不定参数特性来定义占位符,从而简化数据处理的过程

    function tag(literals, ...substitutions) {
      // 返回一个字符串
    }
    

    下面定义一个tag标签函数,模拟模板字面量的默认行为。

    function tag(literals, ...substitutions) {
      let ret = ''
      // 使用substitutions的数量进行循环,而不是literals的数量
      for (let i = 0; i < substitutions.length; i++) {
    	ret += literals[i]
    	ret += substitutions[i]
      }
      // 添加literals的最后一个元素
      ret += literals[literals.length - 1]
      return ret
    }
    
    let name = 'Xiaowang', country = 'China'
    let s = tag`My name is ${name}, I am from ${country}`
    console.log(s) // 'My name is Xiaowang, I am from China'
    

    ...可以把不定参数表示成数组。上面的示例通过遍历substitutions数组(substitutions的元素个数始终比literals少1),交替组合literals和substitutions中的元素,最后加上literals的最后一个元素,完成了模拟模板字面量的默认行为。

    应用

    应用一:过滤HTML字符串,防止用户输入恶意内容

    function saferHTML(literals, ...substitutions) {
      let ret = ''
      for (let i = 0; i < substitutions.length; i++) {
        let s = String(substitutions[i])
    	ret += literals[i]
    	ret += s.replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;");
      }
    
      ret += literals[literals.length - 1]
      return ret
    }
    
    let content = '<script>alert(1)</script>' // 用户输入
    let msg = saferHTML`${content} is safe` // 安全处理
    console.log(msg)
    // &lt;script&gt;alert(1)&lt;/script&gt; is safe
    

    应用二:多语言转换(国际化处理)

    function i18n(literals, ...substitutions) {
      // 数据转换
    }
    
    let name = 'Xiaowang', country = 'China'
    let ret = i18n`My name is ${name}, I am from ${country}!`
    // 我的名字是小王,我来自中国
    

    应用三:模板引擎

    模板字符串本身并不能取代模板引擎,它没有条件判断和循环处理这些功能,但可以通过标签函数,自己添加这些功能

    function tpl(literals, ...substitutions) {
      // 通过匹配特殊字符处理数据
    }
    
    let ret = tpl`
      <ul>
        #for item in ${books}
          <li><i>#{item.title}</i> by #{item.author}</li>
        #end
      </ul>`
    

    raw()

    String.raw()方法常作为模板字面量的处理函数,它的第一个参数应该是一个具有raw属性的对象,且raw属性的值应该是一个数组。

    String.raw({ raw: 'test' }, 0, 1, 2);// 't0e1s2t'
    
    // 等同于
    String.raw({ raw: ['t','e','s','t'] }, 0, 1, 2);
    
    优秀文章首发于聚享小站,欢迎关注!
  • 相关阅读:
    观察者模式
    Java中关于HashMap源码的研究
    抽象工厂模式
    适配器模式
    oracle创建表空间并赋予权限
    外观模式
    oracle中循环读出一个表的信息插入到另外一个表中
    javaScript对金额处理的方式
    装饰器模式
    建造者模式
  • 原文地址:https://www.cnblogs.com/yesyes/p/15352118.html
Copyright © 2020-2023  润新知