eval('"\n"')这个为什么会报错

发布于 2022-09-12 22:19:48 字数 47 浏览 9 评论 0

这个为什么会报错,哪位大神帮忙分析一下原理,知道怎么修改,但是不知道为什么会报错

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

海风掠过北极光 2022-09-19 22:19:48

楼上说的很清楚了,你的换行符是转义了,所以 eval 出来就相当于两行代码,一行各一个双引号,JS 双引号不能换岗,所以报错。
假如你想要让 eval “看到” "\n",应该不转义换行符,那么就是 \\n


一些可能没说清楚的地方:
说字符串 \n 在内存中是数字 10 是正确的,说内存里存了一个换行符也没有问题,这是从不同层面观察字符串。如果更进一步,内存其实也不认识数字 10,只认识二进制数 1010。我之前用 10 来表示换行符主要是帮助区分 JS 代码中的 \n 和实际储存的换行符字符。实际使用时一般不用特别关注编码层面。


我觉得你可能不太理解字符串的原理,说不清楚。
请暂时先忘记一切你已经学到的正确或者错误的有关转义的知识。

让我们看一下这个字符串(为了方便字符串用高亮表示,并且不再用引号包裹)nnn,里面有 3 个字符。
很容易想到储存的时候分成三个字符:

0 1 2
n n n

需要注意的是你的内存并不知道什么是 n,他只认识数字,所以我们把 n 编码成数字,在 ASCII 中也就是 110,那么储存的方式如下(你可以通过 string.charCodeAt(m) 获取字符串第 m 个字符的编码,"n".charCodeAt(0) === 110

总之接下来的表格将不会出现 n 或者别的字符串,只有数字

0 1 2
110 110 110

接下来考虑储存三个换行符。换行也是一个字符,所以在内存中我们也要用一个数字来表示它。由于你现在忘记了什么是转义,不能通过 charCodeAt 获取换行的编码,偷偷告诉你是 10。(回车是 13,不要混淆)

0 1 2
10 10 10

那怎么在 JS 中表示三个换行符构成的字符串?人们很快发现在引号之间空两行可以完成这个任务,但立刻又发现这种方法非常易错和不优雅。

所以人们发明了转义,也就是用普通的,人类可读而且比较容易在键盘上摸到的字符【表示】特殊字符。

到目前为止似乎都是浅显易懂的内容,也确实是浅显易懂的内容。

人们告诉 JS 解析器:当你在俩引号直接读到 一个捺斜杠 \ 接着一个 n 的时候,你既不要把 \ 塞进内存,也不要把 n 塞进内存,而是把一个换行符,也就是整数 10 塞进内存。

所以 JS 在解析阶段,就把 \n 都扔了,只剩下 10。这也就回答了你转义是什么时候发生的,的问题。

所以现在可以很开心地使用 console.log("new\nline") 了,可以看到打印了两行,一行是 new,一行是 line,中间是什么呢?是一个换行符。

好,目前在你并没有注意到(99%)的情况下已经出现了三种换行符。

  1. 【解析器认识的东西】一个捺斜杠 \ 接着一个 n
  2. 【内存认识的东西】整数 10。
  3. 【你认识的东西】屏幕上空了一行

3 放在一边不管,现在我严重怀疑你分不清 1 和 2,所以我把 2 的描述从通常的 一个换行符字符 改成了整数 10。


再看 eval,有人会告诉你 eval 能帮你动态执行一些代码。但是 eval 的原理是什么?他一个函数,何德何能执行代码啊?(当然 jsjs 可以做到)他肯定是把活给了解析器啊。

观察以下代码:

console.log("new\nline")
eval('console.log("new\\nline")')

我们分析一下代码中的 n 和换行符是如何被处理的(因为我只查了这两个字符的编码值)

console.log("new\nline")
--^
  普通的 n,是函数名的一部分。不在字符串里,所以没有惨遭变成数字 的命运。
-------------^
                字符串中的 n,被解析器用残忍的手段变成了 110。
-----------------^
                 字符串中且在斜杠后面的 n,两个一起变成了 10。
--------------------^
                    也很普通。
------------------------^
                        程序中的换行,假如没有它,就得在下一行 eval 前面加个分号。
+^-^+

所以传给 console.log 的是什么呢?
一列整数:(? 是我没查的编码值)    
110 ? ? 10 ? ? 110 ?

eval('console.log("new\\nline")')
--------^
        在字符串中!110
-------------------^
                   在同一个字符串中!110
------------------------^
                        还在那个字符串中,前面有斜杠!但是斜杠自身被另一个斜杠转义了,失去了转义 n 的功能。110
---------------------------^
                           110
+^-^+

咦?全是 110?我的 10 在哪?(如果你是这么想的,恭喜你已经理解了【字符】的本质:数字而已。
还没有完:eval 会把接收到的字符串传给解析器,第二轮解析开始。

console.log("new\nline")
+^-^+
竟然和第一行一样了!
如果我们没有转义斜杠会发生什么呢?eval 会收到一个引号中间的,致命的 10。也就是在你的字符串中间出现了一个换行,而且字符串不是用反引号 ` 包裹的。

console.log("new
line")

这时会发生什么呢?

Uncaught SyntaxError: Invalid or unexpected token

跃然屏上。

希望搞懂了,加油(
神妖 2022-09-19 22:19:48

因为不是有效的 JS 表达式或语句啊。

在 JS 看来就相当于有两行长这样的代码:

"
"

哪怕你不用 eval,就这两行你直接写到 script 里它也是不能执行的啊。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文