const { width } = (ctx as any).measureText('结果统计')
(ctx as any).fillText('结果统计', x - width / 2, y + fontSize / 2)
使用const 定义width,底下没有直接使用width,而是相当于重新定义了一个,
使用var定义width,底下相当于重新定义一个width,没有使用过。
为啥没有使用上边定义的width,难道是变量作用域出了问题吗?
const { width } = (ctx as any).measureText('结果统计')
(ctx as any).fillText('结果统计', x - width / 2, y + fontSize / 2)
使用const 定义width,底下没有直接使用width,而是相当于重新定义了一个,
使用var定义width,底下相当于重新定义一个width,没有使用过。
为啥没有使用上边定义的width,难道是变量作用域出了问题吗?
10 回答11.3k 阅读
5 回答4.9k 阅读✓ 已解决
4 回答3.2k 阅读✓ 已解决
2 回答2.8k 阅读✓ 已解决
3 回答2.4k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
这个跟作用域关系不大,本质上是词法解析引起的问题.
这里看起来是两行,但会被当作一条语句去解析,像下面这样
最终转译成 JS 如下,看出问题了吧.
要修复也很简单,只要在
(ctx as any)
前加分号就好了实际上就是 JS 中常见的分号插入机制(Automatic semicolon insertion)的问题.
虽然写的 TS,心里要明白实际上本质还是 JS.
补充
JS 中并不是不用写分号,而是可以选择不写分号.这是由于 ASI(分号插入机制)的存在.
分号在 JS 中是终结符的作用,出现分号是告诉 JS 引擎分号后面是另外一个语句,相当于给句子断句.
即使没有分号,大多数情况下,JS 引擎能根据规则去断句(大部分是在换行处),这个规则依据的就是 ASI 机制.但有些特殊情况(上一行尾跟下一行首可以组成一个合法语句的情况),ASI 是不起作用的.比如:
这里虽然是两行,但是
foo
可以和(1)
组合成foo(1)
这样的合法语句,这种情况 ASI 就不会生效,不会在foo
后面插入分号.那如果我们本意是将foo
赋值给a
,而不是把foo(1)
赋值给a
,那就需要在foo
和(1)
之间插入分号.如下:像这样的特殊情况不多,对于习惯不加分号的人来说,只要判断行首有没有出现这五个字符
[ ( + - /
,然后在这些情况前面加分号就够了.当然,这只是比较浅显的解释,更多详细可以参考下面的文章
JavaScript 语句后应该加分号么?
ECMA262 Automatic Semicolon Insertion