ts变量作用域的问题

张巨侠
  • 340
const { width } = (ctx as any).measureText('结果统计')
(ctx as any).fillText('结果统计', x - width / 2, y + fontSize / 2)

image.png
使用const 定义width,底下没有直接使用width,而是相当于重新定义了一个,
使用var定义width,底下相当于重新定义一个width,没有使用过。
为啥没有使用上边定义的width,难道是变量作用域出了问题吗?
image.png

回复
阅读 412
2 个回答

这个跟作用域关系不大,本质上是词法解析引起的问题.

const { width } = (ctx as any).measureText('结果统计')
(ctx as any).fillText('结果统计', x - width / 2, y + fontSize / 2)

这里看起来是两行,但会被当作一条语句去解析,像下面这样

const { width } = (ctx as any).measureText('结果统计')(ctx as any).fillText('结果统计', x - width / 2, y + fontSize / 2)

最终转译成 JS 如下,看出问题了吧.

const { width } = ctx.measureText('结果统计')(ctx).fillText('结果统计', x - width / 2, y + fontSize / 2);

要修复也很简单,只要在 (ctx as any) 前加分号就好了

const { width } = (ctx as any).measureText('结果统计')
;(ctx as any).fillText('结果统计', x - width / 2, y + fontSize / 2)

实际上就是 JS 中常见的分号插入机制(Automatic semicolon insertion)的问题.

虽然写的 TS,心里要明白实际上本质还是 JS.

补充

JS 中并不是不用写分号,而是可以选择不写分号.这是由于 ASI(分号插入机制)的存在.

分号在 JS 中是终结符的作用,出现分号是告诉 JS 引擎分号后面是另外一个语句,相当于给句子断句.

即使没有分号,大多数情况下,JS 引擎能根据规则去断句(大部分是在换行处),这个规则依据的就是 ASI 机制.但有些特殊情况(上一行尾跟下一行首可以组成一个合法语句的情况),ASI 是不起作用的.比如:

var a = foo
(1)

这里虽然是两行,但是 foo 可以和 (1) 组合成 foo(1) 这样的合法语句,这种情况 ASI 就不会生效,不会在 foo 后面插入分号.那如果我们本意是将foo赋值给a,而不是把foo(1)赋值给a,那就需要在foo(1)之间插入分号.如下:

var a = foo
;(1)

像这样的特殊情况不多,对于习惯不加分号的人来说,只要判断行首有没有出现这五个字符[ ( + - /,然后在这些情况前面加分号就够了.

我个人比较喜欢不加分号,不过这些其实都无所谓,都是编辑器在做的事情,只要把项目配置好,加或不加都是一个命令的事情.

当然,这只是比较浅显的解释,更多详细可以参考下面的文章

image.png

好像也没啥问题

难道你的语言环境不支持解构嘛

你知道吗?

宣传栏