javascript document.write:未捕获的语法错误:输入意外结束

lskq00tm  于 2021-09-13  发布在  Java
关注(0)|答案(2)|浏览(302)

我试图开发一个实时代码编辑器。
代码给出了错误:

Uncaught SyntaxError: Unexpected end of input

问题在哪里,或者有什么解决办法?

function compile() {
  let htmlContent = document.getElementById('html');
  let cssContent = document.getElementById('css');
  let jsContent = document.getElementById('js');

  let output = document.getElementById('output');

  output = output.contentWindow || output.contentDocument.document || output.contentDocument;

  let doc = output.document;

  doc.open();
  doc.write(
    `<style>${cssContent.value}</style>
                <body>${htmlContent.value}</body>
                <script>${jsContent.value}</script>`
  );
  doc.close();
}
<textarea id="html" cols="30" rows="10"></textarea>
<textarea id="css" cols="30" rows="10"></textarea>
<textarea id="js" cols="30" rows="10"></textarea>
<button onclick="compile()">Run</button>
<iframe id="output"></iframe>
yduiuuwa

yduiuuwa1#

如果在脚本标记中插入,无论它是引号中的字符串、撇号,甚至是模板文字,它都将始终关闭脚本标记。你必须逃避它。

doc.write(
  `<style>${cssContent.value}</style>
   <body>${htmlContent.value}</body>
   <script>${jsContent.value}<\/script>`);

但是,如果使用外部脚本,它应该可以正常工作,而不会转义。
此处有更多讨论:“未终止的模板文字”当文字包含脚本标记时出现语法错误

ni65a41a

ni65a41a2#

关闭脚本标记
正如@sanmeet在其(已删除的)回答中指出的,错误是由于没有转义end script标记中的反斜杠引起的:如果html解析器解码 <script> 标记,它将输入缓冲到下一个 </script> 标记并将其传递给javascript编译器。在本例中,它将脚本的剩余部分作为文本处理,并将其放入body元素中。
重用变量名和类名
将结束标记转义到 <\/script> 这揭示了另一个问题。google chrome在以下情况下不会重新初始化全局变量空间: document.open 被称为(正如正确的历史实践一样)。不幸的是,firefox已经改变了它的行为来跟随套件,并且不再重新初始化变量。
一个可能的解决方案是创建一个新的 iframe 元素每次 run 按钮被点击。下面的示例扩展了发布的代码以创建新的 iframe . 如果你申报 let , constclass 在javascript框中,您现在可以重复按run按钮,而无需更改变量和类名。

function compile() {
  let htmlContent = document.getElementById('html');
  let cssContent = document.getElementById('css');
  let jsContent = document.getElementById('js');

  let output = document.getElementById('output');
  let replacement = document.createElement('iframe');
  replacement.id = "output";
  output.replaceWith( replacement);
  output = replacement;

  output = output.contentWindow || output.contentDocument.document || output.contentDocument;

  let doc = output.document;

  doc.open();
  doc.write(
    `<style>${cssContent.value}</style>
                <body>${htmlContent.value}</body>
                <script>${jsContent.value}<\/script>`
  );
  doc.close();
}
<textarea id="html" cols="30" rows="10"  placeholder="html..."></textarea>
<textarea id="css" cols="30" rows="10" placeholder="css..."></textarea>
<textarea id="js" cols="30" rows="10" placeholder="js..."></textarea>
<button onclick="compile()">Run</button>
<iframe id="output"></iframe>

代码段错误
执行代码段会在尝试访问时生成安全错误 doc . 它在浏览器中按预期工作。

相关问题