String.raw()

String.raw() 静态方法是 模板字面量 的标签函数。这类似于 Python 中的 r 前缀,或 C# 中字符串字面量的 @ 前缀。它用于获取模板字面量的原始字符串形式——也就是说,替换(例如 ${foo})会被处理,但转义序列(例如 \n)不会。

试一试

语法

js
String.raw(strings)
String.raw(strings, sub1)
String.raw(strings, sub1, sub2)
String.raw(strings, sub1, sub2, /* …, */ subN)

String.raw`templateString`

参数

字符串

格式良好的模板字面量数组对象,例如 { raw: ['foo', 'bar', 'baz'] }。应为一个对象,其 raw 属性的值为一个类似数组的字符串对象。

sub1、…、subN

包含替换值。

模板字符串

一个 模板字面量,可以选择包含替换(${...})。

返回值

给定模板字面量的原始字符串形式。

异常

TypeError

如果第一个参数没有 raw 属性,或者 raw 属性为 undefinednull,则抛出此异常。

描述

在大多数情况下,String.raw() 与模板字面量一起使用。上面提到的第一个语法很少使用,因为 JavaScript 引擎会为您调用此方法并传递正确的参数(就像其他 标签函数 一样)。

String.raw() 是唯一的内置模板字面量标签。它与未标记的字面量具有相似的语义,因为它连接所有参数并返回一个字符串。您甚至可以使用普通的 JavaScript 代码重新实现它。

警告:您不应将 String.raw 直接用作“标识”标签。有关如何实现此目的,请参阅 构建标识标签

如果 String.raw() 被调用时,其 raw 属性没有 length 属性或其 length 为非正数,则返回空字符串 ""。如果 substitutions.length < strings.raw.length - 1(即没有足够的替换来填充占位符——这在格式良好的标记模板字面量中不可能发生),则其余的占位符将填充空字符串。

示例

使用 String.raw()

js
String.raw`Hi\n${2 + 3}!`;
// 'Hi\\n5!', the character after 'Hi'
// is not a newline character,
// '\' and 'n' are two characters.

String.raw`Hi\u000A!`;
// 'Hi\\u000A!', same here, this time we will get the
// \, u, 0, 0, 0, A, 6 characters.
// All kinds of escape characters will be ineffective
// and backslashes will be present in the output string.
// You can confirm this by checking the .length property
// of the string.

const name = "Bob";
String.raw`Hi\n${name}!`;
// 'Hi\\nBob!', substitutions are processed.

String.raw`Hi \${name}!`;
// 'Hi \\${name}!', the dollar sign is escaped; there's no interpolation.

将 String.raw 与 RegExp 一起使用

String.raw 模板字面量与 RegExp() 构造函数结合使用,您可以创建具有动态部分的正则表达式(这在正则表达式字面量中是不可能的),而无需双重转义(\\)正则表达式转义序列(这在普通字符串字面量中是不可能的)。这在包含大量斜杠的字符串(例如文件路径或 URL)中也很有价值。

js
// A String.raw template allows a fairly readable regular expression matching a URL:
const reRawTemplate = new RegExp(
  String.raw`https://developer\.mozilla\.org/en-US/docs/Web/JavaScript/Reference/`,
);

// The same thing with a regexp literal looks like this, with \/ for
// each forward slash:
const reRegexpLiteral =
  /https:\/\/developer\.mozilla\.org\/en-US\/docs\/Web\/JavaScript\/Reference\//;

// And the same thing written with the RegExp constructor and a
// traditional string literal, with \\. for each period:
const reStringLiteral = new RegExp(
  "https://developer\\.mozilla\\.org/en-US/docs/Web/JavaScript/Reference/",
);

// String.raw also allows dynamic parts to be included
function makeURLRegExp(path) {
  return new RegExp(String.raw`https://developer\.mozilla\.org/${path}`);
}

const reDynamic = makeURLRegExp("en-US/docs/Web/JavaScript/Reference/");
const reWildcard = makeURLRegExp(".*");

构建标识标签

许多工具对由特定名称标记的字面量进行特殊处理。

js
// Some formatters will format this literal's content as HTML
const doc = html`<!DOCTYPE html>
<html lang="en-US">
  <head>
    <title>Hello</title>
  </head>
  <body>
    <h1>Hello world!</h1>
  </body>
</html>
`;

有人可能会天真地将 html 标签实现为

js
const html = String.raw;

实际上,这在上述情况下有效。但是,由于 String.raw 会连接原始字符串字面量而不是“已处理”的字符串字面量,因此不会处理转义序列。

js
const doc = html`<canvas>\n</canvas>`;
// "<canvas>\\n</canvas>"

对于“真正的标识”标签,这可能不是您想要的,其中标签纯粹用于标记并且不会更改字面量的值。在这种情况下,您可以创建一个自定义标签并将“已处理”(即已处理转义序列)的字面量数组传递给 String.raw,假装它们是原始字符串。

js
const html = (strings, ...values) => String.raw({ raw: strings }, ...values);
// Some formatters will format this literal's content as HTML
const doc = html`<canvas>\n</canvas>`;
// "<canvas>\n</canvas>"; the "\n" becomes a line break

请注意,第一个参数是一个对象,它具有一个 raw 属性,其值是一个类似数组的对象(具有 length 属性和整数索引),表示模板字面量中分隔的字符串。其余参数是替换。由于 raw 值可以是任何类似数组的对象,因此它甚至可以是字符串!例如,'test' 被视为 ['t', 'e', 's', 't']。以下是 `t${0}e${1}s${2}t` 的等效项

js
String.raw({ raw: "test" }, 0, 1, 2); // 't0e1s2t'

规范

规范
ECMAScript 语言规范
# sec-string.raw

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅