就功能而言,选项1)和2)实现了相同的结果。我猜Typescript编译器将这些选项翻译成相同的JavaScript代码。或者至少Javascript解释器会这样做,如果Typescript编译器没有进行这种优化的话。我习惯在循环中声明变量not以避免重新声明,这对于具有非平凡构造函数的对象变得很有趣。因为构造函数和析构函数在选项1中的每次迭代中都被调用。但是选项2也为更复杂的对象提供了以下原因(现在):
- 循环外部不可访问
- 表示不会重新分配
- 有些人觉得它更简洁,更容易阅读
关于作用域声明变量(let/const)的最佳实践是什么?
第一章
let someVar = "";
this.array.forEach(item => {
someVar = item;
// no further reassignment of someVar
...
});
字符串
this.array.forEach(item => {
const someVar = item;
...
});
型
3条答案
按热度按时间mm9b1k5b1#
需要明确的是,作用域与TypeScript编译几乎没有关系(就我所知,在这种情况下没有关系),更多的是与JavaScript本身有关。你可以阅读TypeScript添加到JavaScript here的内容,但它更多的是与类型有关,而不是与变量声明有关。你可能指的是将JavaScript编译为低级语言,但我不确定你的意思。
在我看来,如果你需要在循环后访问变量,那么只使用case 1(在循环外用'let'声明)。如果你不需要这样做(即,如果你只需要在循环的每次迭代中访问变量),那么在循环中用
const
声明它(case 2)。如果只在循环的 * 某些 * 迭代中更新/设置变量的值,但希望在大多数或所有迭代中读取由循环的先前迭代更新的值,则也可以使用
let
(情况1)。zd287kbt2#
就功能而言,选项1)和2)实现了相同的结果。我猜Typescript编译器会将这些选项翻译成相同的JavaScript代码。或者至少Javascript解释器会这样做,如果Typescript编译器不做这种优化的话。
选项1)和2)不是同一个代码,无论是在TS还是JS中。
我习惯于在循环中声明变量not以避免重复声明,这对于具有非平凡构造函数的对象来说很有趣。因为构造函数和析构函数在选项1)中的每次迭代中都被调用。
TS/JS中没有析构函数,对象会被垃圾收集器销毁和清理。如果你正在与本机模块(C或C++)发生冲突,那么你通常会有一个公共
dispose
方法来做必要的清理(或者让C++析构函数做它的工作)。让我们回到你的问题。JavaScript是一种解释型语言,这意味着通常没有编译步骤来生成必要的代码来处理将变量推入堆栈和从堆栈弹出变量。这在运行时按需发生。
在这两个选项中,
item
变量都被推送到堆栈中,使其在forEach
回调中可用,因此它总是为数组中的每个项目重新声明。这使得此语句无效I was used to declare variables **not** inside a loop to avoid re-declaration
。现在,解释型语言与编译型语言相比可能非常慢。出于这个原因,一些非常聪明的人想出了一些优化技术来加速语言的解释型本质。其中一种技术称为即时(JIT)编译,这意味着如果运行时检测到某段代码被多次调用,它可以将其编译为更优化的代码并使用它,而不是一次又一次地重新解释代码。
回到你的代码示例,在选项1)中,JIT可能会被愚弄,因为它有外部引用,所以它不能优化循环。而对于选项2),它知道所有需要的引用都在循环内,它可以继续完全优化它。所以,从技术上讲,选项2更“正确”,因为它使用了预期的范围:尽可能在
local
范围内使用变量,而不是无缘无故地在外部范围内使用变量。ukxgm1gy3#
就Typescript而言,我不确定你所说的“它会将两个选项转换为相同的代码”到底是什么意思。这两个例子是完全不同的代码,所以这两个导致相同代码的例子没有任何意义。
在可读性方面,如果你声明了
forEach
之外的东西,我会猜测它会在其他地方使用。这可能会导致一些混乱。如果外部作用域不需要变量,只需将其保留在回调函数的本地。编辑:我提供了一些更多的信息,因为我在阅读您的评论时更了解您的问题。
Typescript不关心分析代码的运行时。这项工作超出了它的范围。Typescript所做的就是在Javascript之上为类型提供这种特殊的语法。编译器然后进行类型检查,然后再次输出JavaScript代码。然后通常代码会传递给编译器,在那里你可以做一些优化,比如死代码消除,从未使用的变量到未使用的模块。但是你不会从这些构建工具中看到改变运行时执行的优化。当然,你绝对可以尝试使用工具在运行时代码中进行这样的修改,但是为什么要这样做呢?这就像在把代码发送到编译器之前,先构建一个优化代码的工具,编译器本身会处理所有的优化。为什么类型检查工具、转译器或编译器要费心去做呢?
这样的优化肯定会发生,但来自JS引擎本身。
实际上,你可以尝试用Typescript编译器编译你的例子,看看发生了什么。