为什么插入 document.write 的脚本可以更改变量
Why can scripts inserted with document.write change variables
为什么下面的脚本打印 33 而不是 31?
<script>
var i = 1;
document.write("<script> i=3; document.write(i); </scr" + "ipt>");
document.write(i);
</script>
这个打印了31,有什么区别?
<script>
var i = 1;
document.write("<script> i=3; document.write(i); </scr" + "ipt>" + i);
</script>
这是它的工作方式顺序:
- 定义一个名为
i
的变量,其值为1
。 -
将新脚本写入文档
2.1. 这个新脚本将
i
重新定义为3
。2.2. 脚本将
i
写入文档(请记住,现在3
)。 -
您再次将
i
写入文档(值与重新定义它时的值仍然相同,3
)到文档中。 - 最终结果是
33
,因为你写了两次3
。
这是第二个块的顺序:
- 定义一个变量
i
,值为1
。 - JavaScript 连接字符串和
i
,创建"<script> i=3; document.write(i); </script>1"
(注意末尾的1
,这是为了做连接) -
JavaScript 将新的串联字符串写入文档。
3.1.
i
被重新定义为3
。3.2.
document.write
的i
(之前已重新定义为3
)。 -
由于串联和
document.write
,您最终会得到"3<script> i=3; document.write(i); </script>1"
作为最终文档。 显然,<script>
的内容是不可见的。 所以你最终会得到31
.
为了使第一个示例的输出为 31,在解析器对该输出执行任何操作之前,最外层的脚本块必须一直运行并生成其所有输出。这是一种完全合理的方式来认为它会起作用(我认为它多年来一直如此);这是不正确的。:-)浏览器比这更主动。
浏览器的解析器和 JavaScript 引擎必须协同工作,以处理不使用 async
或 defer
属性的脚本标记。关于这一点的两个关键点:
-
当解析器看到一个完整的
script
块时,它会尖叫停止并将其交给 JavaScript 引擎立即运行。 -
调用
document.write
向解析器提供新令牌;如果解析器看到完整的令牌,它将在调用document.write
期间处理它。如果该完整令牌是脚本块,则"处理它"涉及在当前调用 JavaScript 引擎期间再次调用它。您可以将每个document.write
调用视为对解析器的调用,将每个完整的脚本块视为对 JavaScript 引擎的调用。与函数调用一样,这些可以嵌套。
第二点是为什么你看到的是33而不是31。您编写document.write
脚本是在调用 document.write
期间执行的,而不是之后执行的,因此i
在该document.write
完成之前更新为 3
(和输出)。因此,当您到达主脚本块末尾的document.write
时,i
已经更改为 3
,并且已经输出了一次。
在第二个示例中,您在调用document.write
之前使用i
(当您将其附加到文本时),因此您当然会看到i
的值,就像它一样,1
。
这可能会使调用顺序更清晰:
<script>
document.write("<script>document.write('a');</scr" + "ipt>");
document.write('b');
</script>
结果是ab
,而不是ba
。第一个document.write
的代码输出在最后一个document.write
运行之前运行,因此中间document.write
的输出显示在最后一个输出之前。
>在第一种情况下注入document.write
在第一种情况下重新定义了变量 i,因此第二种document.write
也打印了 3。
在第二种情况下,您只有一个 document.write,它将 i=1 的原始值附加到注入document.write
的输出中。
有趣的是,有人可能会在这里期待甚至另一个组合"13")))
- IF 语句不改变变量的结果
- 为什么不是'这个CanvasJS脚本动态地改变变量
- 在php中改变变量,但在javascript中相同的变量不变
- 为什么Javascript不使用onChange来改变变量?
- 添加一个DOM/SVG元素与d3 javascript库改变变量引用/范围,为什么
- 通过点击按钮改变变量的值
- 在按下键后改变变量
- JQuery改变变量/成本后点击
- Eventlistener点击不改变变量时按下
- 改变变量中的链接
- 不能让函数改变变量
- Javascript滑块动态改变变量
- 通过html按钮改变变量
- Jquery在点击时改变变量
- 不能改变变量
- 为什么我的精灵在不改变变量的情况下加速
- 在javascript的文字函数中改变变量的值
- jQuery用子元素改变变量
- 改变变量&设置日期反应原生
- Ajax文件检查成功后不改变变量