ES6 Raw String Access 的实际用途是什么?

What are the actual uses of ES6 Raw String Access?

ECMAScript 6 中引入的 String.raw 原始字符串访问的实际用途是什么?

// String.raw(callSite, ...substitutions)

function quux (strings, ...values) {
    strings[0] === "foo\n"
    strings[1] === "bar"
    strings.raw[0] === "foo\n"
    strings.raw[1] === "bar"
    values[0] === 42
}

quux `foo\n${ 42 }bar`

String.raw `foo\n${ 42 }bar` === "foo\n42bar"

我浏览了以下文档。

http://es6-features.org/#RawStringAccess

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw

http://www.2ality.com/2015/01/es6-strings.html

https://msdn.microsoft.com/en-us/library/dn889830(v=vs.94).aspx

The only the thing that I understand, is that it is used to get the raw string form of template strings and used for debugging the template string.

什么时候可以用于实时开发?他们称此为标记函数。这是什么意思?

我遗漏了哪些具体用例?

模板字符串在很多情况下都很有用,我将在下面解释。考虑到这一点, String.raw 防止转义被解释。这在您想要包含转义字符但又不想将其转义的任何模板字符串中都非常有用。一个简单的例子如下:

var templateWithBackslash = String.raw `someRegExp displayed in template /^\//`

模板字符串中有一些值得注意的地方。

  1. 它们可以毫无问题地包含未转义的换行符。
  2. 它们可以包含“${}”。在这些大括号内 javascript 被解释为

(Note: running these will output the result to your console [in browser dev tools])

使用换行符的示例:

var myTemplate = `
<div class="myClass">
  <pre>
    My formatted text
    with multiple lines
    {
      asdf: "and some pretty printed json"
    }
  </pre>
</div>
`
console.log(myTemplate)

如果你想用 Javascript 中的普通字符串执行上述操作,它将如下所示:

var myTemplate = "\
<div class="myClass">\
  <pre>\
    My formatted text\
    with multiple lines\
    {\
      asdf: "and some pretty printed json"\
    }\
  </pre>\
</div>"
console.log(myTemplate)

您会注意到第一个可能看起来更好(无需转义换行符)。

对于第二个,我将使用相同的模板字符串,但也会插入一些漂亮的打印 JSON。

var jsonObj = {asdf: "and some pretty printed json", deeper: {someDeep: "Some Deep Var"}}
var myTemplate = `
<div class="myClass">
  <pre>
    My formatted text
    with multiple lines
    ${JSON.stringify(jsonObj, null, 2)}
  </pre>
</div>
`
console.log(myTemplate)

首先,有几件事:

  • 模板字符串是模板文字的旧名称。
  • 标签是一个函数。
  • String.raw是一种方法。
  • String.raw `foo\n${ 42 }bar\` 是标记的模板文字。
  • 模板文字基本上是花哨的字符串。
  • 模板文字可以插入。
  • 模板文字可以是多行的,无需使用 \
  • 需要
  • String.raw转义转义符\.

尝试将包含换行符的字符串 \n 通过使用换行符的函数。

console.log("This\nis\nawesome"); // "This\nis\nawesome"
console.log(String.raw`This\nis\nawesome`); // "This\nis\nawesome"

如果您想知道,console.log 不是其中之一。但是 alert 是。通过 http://learnharmony.org/ 尝试 运行 这些。

alert("This\nis\nawesome");
alert(String.raw`This\nis\nawesome`);

但是等等,这不是 String.raw 的用途。

String.raw 方法的可能用途:

  • 显示不解释反斜杠字符(\n、\t)等的字符串
  • 显示输出代码。 (如下例)
  • 无需转义即可在正则表达式中使用 \
  • 打印 windows director/sub-directory 个位置,而无需过多使用 \。 (他们用\记得。还有,哈哈)

这里我们可以在单个警报中显示输出和代码 window:

alert("I printed This\nis\nawesome with " + Sring.raw`This\nis\nawesome`);

不过,如果它的主要用途是取回原始字符串,那就太好了。 赞:

var original = String.raw`This    is     awesome.`;

其中 original 会变成:This\tis \tawesome.。可悲的是,情况并非如此。

参考文献:

我能想到的 String.raw 的最佳且几乎唯一的用例是,如果您尝试使用像 Steven Levithan 的 XRegExp library 这样的东西来接受带有明显反斜杠的文本。使用 String.raw 可以让您写出语义清晰的内容,而不必考虑加倍反斜杠,就像您可以在 Java 脚本本身的正则表达式文字中一样。

例如,假设我正在维护一个网站,我发现了这个:

var isSingleUnicodeWord = /^\w+$/;

...这意味着检查一个字符串是否仅包含 "letters." 两个问题:A) 在人类语言领域有成千上万的 "word" 个字符 \w不认识,因为它的定义是以英语为中心的; B) 它包括 _,许多人(包括 Unicode 联盟)认为这不是 "letter."

因此,如果我们在网站上使用 XRegExp,因为我知道它支持 \pL\p 用于 Unicode 类别,L 用于 "letter"),我可能会很快将其换成:

var isSingleUnicodeWord = XRegExp("^\pL+$"); // WRONG

然后我想知道为什么它不起作用,捂脸,然后返回并转义那个反斜杠,因为它被字符串文字消耗了。

在这个简单的正则表达式中很容易,但在复杂的事情中,记住将所有这些反斜杠加倍是一种维护痛苦。 (只要问 Java 试图使用 Pattern 的程序员。)

输入String.raw:

let isSingleUnicodeWord = XRegExp(String.raw`^\pL+$`);

示例:

let isSingleUnicodeWord = XRegExp(String.raw`^\pL+$`); // L: Letter
console.log(isSingleUnicodeWord.test("Русский"));      // true
console.log(isSingleUnicodeWord.test("日本語"));        // true
console.log(isSingleUnicodeWord.test("العربية"));      // true
console.log(isSingleUnicodeWord.test("foo bar"));      // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/3.1.1/xregexp-all.min.js"></script>

现在我只是退后一步,写下我的意思。我什至不必担心模板文字中使用的 ${...} 构造来进行替换,因为我想将量词 {...} 应用于行尾断言的可能性很大($) 是...低。所以我可以愉快地使用替换而不用担心反斜杠。可爱


话虽如此,但如果我经常这样做,我可能想编写一个函数并使用标记模板而不是 String.raw 本身。但是正确地做起来却出奇地尴尬:

// My one-time tag function
function xrex(strings, ...values) {
  let raw = strings.raw;
  let max = Math.max(raw.length, values.length);
  let result = "";
  for (let i = 0; i < max; ++i) {
    if (i < raw.length) {
      result += raw[i];
    }
    if (i < values.length) {
      result += values[i];
    }
  }
  console.log("Creating with:", result);
  return XRegExp(result);
}

// Using it, with a couple of substitutions to prove to myself they work
let category = "L";                                // L: Letter
let maybeEol = "$";
let isSingleUnicodeWord = xrex`^\p${category}+${maybeEol}`;
console.log(isSingleUnicodeWord.test("Русский"));  // true
console.log(isSingleUnicodeWord.test("日本語"));    // true
console.log(isSingleUnicodeWord.test("العربية"));  // true
console.log(isSingleUnicodeWord.test("foo bar"));  // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/xregexp/3.1.1/xregexp-all.min.js"></script>

如果您在很多地方都使用它,也许麻烦是值得的,但对于几个快速的地方,String.raw 是更简单的选择。

在 NodeJS 中,文件路径处理非常方便:

var fs=require('fs');
var s =  String.raw`C:\Users\<username>\AppData\Roaming\SomeApp\someObject.json`;
var username = "bob"
s=s.replace("<username>",username)
fs.readFile(s,function(err,result){
    if (err) throw error;
    console.log(JSON.parse(result))
})

它提高了 Windows 上文件路径的可读性。 \ 也是一个相当常见的分隔符,所以我完全可以理解为什么它在一般情况下会有用。然而,\ 仍然逃脱是非常愚蠢的 `... 所以最终:

String.raw`C:\Users\` //#==> C:\Users\`
console.log(String.raw`C:\Users\`) //#==> SyntaxError: Unexpected end of input.

使用

(必备知识:tstring .)

而不是:

console.log(`\a\b\c\n\z\x12\xa9\u1234\u00A9\u{1234}\u{00A9}`); 

.你可以:

console.log(String.raw`\a\b\c\n\z\x12\xa9\u1234\u00A9\u{1234}\u{00A9}`);

"Escaping"

<\u> 很好,但是 <\u> 需要 "escaping",例如:

console.log(String.raw`abc${'\u'}abc`);

.嘟嘟 <\x>, <\x>, <console.log(String.raw`abc${`\x`}abc`)>;

.<\`>, <`>, <console.log(String.raw`abc${`\``}abc`)>;

.<${>, <${&>, <console.log(String.raw`abc${`$\{`}abc`)>;

.<\1>(直到 <\7>),<</code>>,<<code>console.log(String.raw`abc${`\1`}abc`)>;

.<\>, 终端单元 <\>, <console.log(String.raw`abc${`\`}`)>.


还有一个新的 "latex" 字符串。比照§.

我发现它对测试很有用 我的正则表达式。假设我有一个 RegExp 应该匹配行尾注释,因为 我想删除它们。但是,它不能 匹配正则表达式的源代码,例如 /// 。 如果您的代码包含 /// 它不是 EOL 注释的开始但 RegExp,如 根据 JavaScript 语法规则。

我可以测试我的 RegExp 是否在变量 patEOLC 中 与///匹配或不匹配:

String.raw`/\//` .match (patEOLC)

换句话说,这是一种让我的方式 code "see" 编码它存在的方式 源代码,而不是它存在的方式 读取后在内存中 从源代码到内存中,用 删除所有反斜杠。

这是"escape escaping"的一种方式,但是 无需单独进行 对于字符串中的每个反斜杠,但是 同时为所有这些。

这是一种表达方式 (反引号)字符串反斜杠 将表现得像任何其他人一样 性格,没有什么特别的 意义或解释。

除了用作标签外,String.raw 还可用于实现新的标签功能,作为一种工具来执行大多数人使用怪异循环执行的交错操作。例如,比较:

function foo(strs, ...xs) {
    let result = strs[0];
    for (let i = 0; i < xs.length; ++i) {
      result += useFoo(xs[i]) + strs[i + 1];
    }
    return result;
}

function foo(strs, ...xs) {
    return String.raw({raw: strs}, ...xs.map(useFoo));
}