首页
/ freeCodeCamp JavaScript 基础教程精读:用反斜杠(\)转义字符串中的字面引号

freeCodeCamp JavaScript 基础教程精读:用反斜杠(\)转义字符串中的字面引号

2026-09-07 12:34:05作者:庞队千Virginia

本指南以 freeCodeCamp 开源课程《Basic JavaScript》挑战块中的一道经典编程挑战——"Escaping Literal Quotes in Strings"(56533eb9ac21ba0edf2244b5.md)为蓝本,系统讲解 JavaScript 中字符串引号冲突的产生原因、反斜杠转义原理、挑战通关步骤,并结合仓库中的相邻课程、schema 校验与断言源码,剖析这道题从"写法"到"判题"的完整链路。读完本文,你将能准确写出含双引号内容的字符串,并看懂 freeCodeCamp 题目中的正则测试断言。

一、问题背景:当字符串内容里必须出现引号时

定义字符串时,首尾必须使用同一种引号(单引号 ' 或双引号 ")。例如:

const doubleQuoteStr = "This is a string";
const singleQuoteStr = 'This is also a string';

JavaScript 与部分其他语言不同,单引号和双引号在语义上完全等价,都可以作为字符串定界符。这一点在原文档所在块的前一个挑战《Quoting Strings with Single Quotes》中有明确说明(见 56533eb9ac21ba0edf2244b4.md)。

现在问题来了:如果字符串内容本身就包含引号呢? 比如想保存一句带引号的对话:

const conversation = 'Finn exclaims to Jake, "Algebraic!"';

JavaScript 会把最外层定界符之后的第一个同种引号当作"字符串结束符"。一旦内容中出现与定界符相同的引号,字符串就会提前终止并抛出语法错误。例如下面的 badStr 会直接报错:

const goodStr = 'Jake asks Finn, "Hey, let\'s go on an adventure?"';
const badStr = 'Finn responds, "Let's go!"'; // SyntaxError:中间的 ' 提前结束了字符串

二、核心解法:反斜杠 \ 转义引号

在 JavaScript 中,把一个 反斜杠(backslash,\ 放在引号前面,即可"转义(escape)"这个引号,让它不再被解释为字符串的结束符,而是作为普通字面字符出现在字符串内部:

const sampleStr = "Alan said, \"Peter is learning JavaScript\".";

此时 JavaScript 引擎会明白:\" 中跟在反斜杠后面的引号并不是字符串的结尾,而是字符串里的内容。用 console.log 打印上述代码,输出为:

Alan said, "Peter is learning JavaScript".

反斜杠 ≠ 正斜杠

需要注意,转义用的反斜杠 \ 与路径/除法中常见的正斜杠 / 是两个完全不同的字符,作用也不同,不能混用。该提示同样出现在相邻挑战 56533eb9ac21ba0edf2244b4.md 的描述中。

更完整的转义序列表

引号并不是字符串中唯一需要转义的字符。紧跟在本文挑战之后的下一个挑战《Escape Sequences in Strings》(56533eb9ac21ba0edf2244b6.md)给出了常用转义序列的完整清单:

代码 输出效果
\' 单引号
\" 双引号
\\ 反斜杠本身
\n 换行
\t 制表符(Tab)
\r 回车
\b 退格
\f 换页

一个容易被忽略的细节:反斜杠自身也需要被转义(写作 \\)才能显示为单个反斜杠,例如 "FirstLine\n\t\\SecondLine\nThirdLine"

三、动手完成挑战

任务目标

题目要求为变量 myStr 赋一个字符串,使其打印到控制台后呈现如下内容:

I am a "double quoted" string inside "double quotes".

也就是说:内容里的两处单词 "double quoted""double quotes" 需要被真实的双引号包围。由于题目希望练习转义,外层定界符也应使用双引号,因此内容中的每个内部双引号都必须写成 \"

起始代码(seed)

仓库中该挑战的种子代码位于同文件 --seed-- 段,初始为:

const myStr = ""; // Change this line

只需替换 "" 中的内容即可。

参考解法

仓库中该挑战的 --solutions-- 段给出的标准答案如下:

const myStr = "I am a \"double quoted\" string inside \"double quotes\".";

数一数:开头的 " 与结尾的 " 是两个未转义的双引号(作为定界符);内容中四个 \"被转义的双引号(作为字面字符)。二者合起来正好对应题目 hints 的计数要求——两个 " 加四个 \"

四、解读测试断言:freeCodeCamp 如何自动判题

这道题的 --hints-- 段包含两条断言,理解它们能帮你更精确地把握题意(原文件位置见 56533eb9ac21ba0edf2244b5.md#L33-L45)。

断言一:统计转义引号的数量

assert(
  __helpers.removeJSComments(code).match(/\\"/g).length === 4 &&
    __helpers.removeJSComments(code).match(/[^\\]"/g).length === 2
);

逐段拆解:

  • __helpers.removeJSComments(code):freeCodeCamp 的测试辅助函数,先剔除源码中的注释,避免注释里的引号干扰统计;
  • /\\"/g:正则字面量中的 \\ 匹配一个真实反斜杠,因此整体匹配的是反斜杠后紧跟双引号(即 \"),g 全局匹配并计数,要求恰好出现 4 次
  • /[^\\]"/g[^\\] 表示"非反斜杠的任意字符",因此匹配的是前面没有反斜杠的双引号,要求恰好出现 2 次(即外层两个定界符)。

这条断言保证了既转义了内部引号,又没有多写或少写转义符。可以试想:如果写成 "I am a "double quoted" string..." 不转义,不仅计数不符,字符串还会在语法层就提前结束。

断言二:校验变量内容

assert(
  /I am a "double quoted" string inside "double quotes(\."|"\.)$/.test(myStr)
);

这条断言直接用正则对 myStr 的值做匹配,确认它包含目标句子 I am a "double quoted" string inside "double quotes" 并在句尾以句点收束。也就是说,题目不仅检查写法,还检查最终字符串值是否与预期完全一致。

五、从仓库源码看一道挑战题的组成与校验

本挑战文件本身就是遵循 freeCodeCamp 课程 Markdown 规范的文档。其 YAML frontmatter 与分节结构如下(完整文件见 curriculum/challenges/english/blocks/basic-javascript/56533eb9ac21ba0edf2244b5.md):

frontmatter 字段 含义
id 56533eb9ac21ba0edf2244b5 全局唯一挑战 ID(同一前缀说明题目在块内相邻)
title Escaping Literal Quotes in Strings 挑战标题
challengeType 1 挑战类型编号
forumTopicId 17568 关联的论坛讨论主题
dashedName escaping-literal-quotes-in-strings URL 友好的英文别名

正文依次包含五个标准分节:# --description--(知识点讲解)、# --instructions--(任务要求)、# --hints--(断言,由 text + 可执行 assert 构成)、# --seed--(编辑器初始代码)与 # --solutions--(参考解法)。这种结构在 basic-javascript 块中的上百个挑战文件里完全一致。

所有挑战文件在入库前都必须通过 schema 校验。在 curriculum/schema/challenge-schema.js 中可以看到:titledescriptiondashedName 均为必填;challengeType 必须是 0~33 的整数(第 180 行);tests 数组必须存在,且每个元素至少要包含 text 与可执行的 testString(第 375-389 行);id 还需符合 ObjectId 格式(第 254 行)。

关于 challengeType: 1 的具体含义,可在共享配置 packages/shared/src/config/challenge-types.ts 中找到定义:文件第 1-2 行 const html = 0; const js = 1;,第 37 行起导出 challengeTypes 对象。即 1 对应 js 类型——本挑战正是 Basic JavaScript 传统编程题的标准类型。

六、绕开转义的替代思路

理解了转义之后,可以进一步思考:是否所有场景都必须用 \"?答案是否定的。由于单双引号等价,你可以选择与内容不冲突的引号作定界符,从而少写甚至不写转义符。

例如本挑战的相邻题目就演示了这一点:当内容里满是双引号时,把外层换成单引号即可免去所有转义(见 56533eb9ac21ba0edf2244b4.md 的解法):

const myStr = '<a href="http://www.example.com" target="_blank">Link</a>';

如果内容中同时需要单、双引号,则只能依赖转义或模板字符串。在现代 JavaScript 中还可使用反引号包裹的模板字符串(template literal):

const s = `Alan said, "Peter is learning JavaScript", and it's fine.`;

不过需要明确:本挑战的教学目标正是"掌握 \" 这种显式转义写法",理解它有助于你读懂他人代码、调试引号相关的语法错误,并更好地理解后续正则表达式与转义序列内容。这也是该挑战被编排在《Quoting Strings with Single Quotes》之后、《Escape Sequences in Strings》之前的原因——先认识转义的必要性,再系统掌握全套转义序列。

七、易错点自查清单

  1. 混用反斜杠与正斜杠:转义符必须是 \,写成 / 无效。
  2. 忘了转义内容中的定界符引号"I am a "double quoted"..." 会在第二个 " 处提前结束字符串并抛 SyntaxError
  3. 在字符串字面量里数错转义数量:可对照断言一的方法——外层定界符 2 个未转义引号 + 4 个 \"
  4. \\\:要输出单个反斜杠必须写 \\,正如相邻挑战《Escape Sequences in Strings》所强调的。

小结

本挑战通过"内容含双引号的字符串"这一最小化场景,教你掌握 JavaScript 转义的核心机制:在引号前加反斜杠 \,让它从"定界符候选"变成"字面字符"。结合同一块内的引号选择技巧与转义序列表,你已具备处理绝大多数引号嵌套场景的能力。想亲自动手验证,可在仓库 curriculum/challenges/english/blocks/basic-javascript/56533eb9ac21ba0edf2244b5.md 中查看题目原始描述,并通过编辑器运行种子代码观察控制台输出。

登录后查看全文
热门项目推荐
相关项目推荐