为啥 var 不被弃用?
Posted
技术标签:
【中文标题】为啥 var 不被弃用?【英文标题】:Why is var not deprecated?为什么 var 不被弃用? 【发布时间】:2018-05-08 00:15:34 【问题描述】:在 ES6 发布后不久,许多消息来源建议我使用“const”和“let”而不是“var”,并且我应该停止在我的 javascript 中使用“var”。
我想知道的是,如果“var”在所有方面都比“let”没有优势,那么他们为什么不直接修复 var,甚至弃用“var”,而不是让它们并排?
【问题讨论】:
因为更改或删除它会破坏大约十亿行代码。var
比let
更有用,当您需要函数作用域而不是块作用域时。
var
仍有用处。
所以你的用例是在块内声明一个变量,然后在块外使用它?
@jhpratt 在任何一家优秀的公司都无法通过代码审查......而且肯定会被任何 linter 盖章。
【参考方案1】:
向后兼容性。
您说得对,使用 var
比使用 let
没有真正的优势 - 如果您在函数开头定义它们,它们的含义基本相同。
您是对的,没有真正的理由使用var
编写新代码(可能除了this,如果相关)。
虽然互联网上有些页面已有数十年的历史,但没有人会重写它们。从语言中删除 var
并没有什么真正的好处。对于 html 和 Javascript 等被解释的语言 - 向后兼容是绝对必要的。
这也是他们选择不简单地重新定义var
的原因。以下面的示例代码为例;
// THIS IS AN EXAMPLE OF BAD CODE. DO NOT COPY AND PASTE THIS.
if (logic)
var output = "true"
else
var output = "false"
console.log(output)
如果将var
更改为类似于let
的行为,那么console.log
将由于范围差异而导致引用错误。
【讨论】:
感谢您的回答。我很感激。然而,您的回答只能解决问题的一部分,即“为什么不弃用 var”。从一开始就重构“var”而不引入任何“let”怎么样?有充分的理由吗? 再次,向后兼容。如果人们以您问题的 cmets 中描述的可怕方式使用var
(并且确实发生了),那么该代码将改变含义并中断,就编写它的开发人员而言可能没有警告。跨度>
我添加了一个例子。
我一直认为你展示的例子是错误的形式。最好在更高的范围内声明变量。这意味着我不认为这是一个很好的使用 var
的例子。
我同意 - 也许我应该让这一点更明显。然而,这是一个例子,说明为什么将 var
更改为意味着 let
是一个坏主意,这就是意图。【参考方案2】:
使用 var const 和 let 各有优缺点。
var
变量声明在代码执行之前被处理。 用 var 声明的 JavaScript 变量的范围是它当前的执行上下文。 在函数外部声明的 JavaScript 变量的作用域是全局的。
let
let 语句允许您创建一个变量,其范围仅限于使用它的块。
const
const 语句的值可以被赋值一次并且不能被重新赋值。 const 语句的作用域类似于 let 语句。
希望你能理解。
【讨论】:
您没有列出var
的任何优势。您也可以在函数或全局级别使用let
,那么除了做一些不愉快的事情(例如在块中声明var
,然后在该块之外使用它)之外,优势在哪里。
"变量声明在代码执行前处理" - the same is true for let
and const
请注意,“变量声明”包括 let 和 const(根据 ECMA-262 §13.3.1),它们都在代码执行之前被处理(但是执行代码时进行分配)。 ;-)【参考方案3】:
我相信有时你需要重新声明一个变量来编写更少的代码。
一个例子是这个生成唯一ID的函数:
function makeUniqueId(takenIds)
do
var id = Number.parseInt(Math.random() * 10);
while (takenIds.includes(id))
可以这样调用
makeUniqueId([1,2,3,4,5,6,7])
在这里,我在 do
块内声明了 id
变量,它被“提升”到函数范围。如果我使用let
,那会导致错误,因为while
块不会看到do
块中的变量。当然,我可以在 do..while
之前声明 let
,但这会使用额外的代码行创建相同的函数作用域变量。
另一个示例是当您将代码复制粘贴到 devtools 控制台并且每次重新声明变量时。
另一个例子。如果你想让你的变量声明接近它们的用法,但仍将它们视为函数全局变量怎么办?如果您以这种方式使用let
,您将在开发工具(所有这些块、块范围)中获得相当混乱的体验。
但是var
将它们“保持”在一个“本地”列表中:
【讨论】:
"如您所见,id 可能会被重新声明很多次......" 不会。当控制进入新的执行上下文(或块范围声明的块)时,声明只被处理一次。在执行 makeUniqueId 的任何主体之前,变量 id 存在于函数范围内。没有 while 块,有一个 while 表达式,你是对的,do 中的 let 声明的范围..while 循环不会扩展到 while 条件,因此如果在做块。 感谢收看! 所有这些用例都不足以成为保留 var 的理由。它带来的混乱和错误多于好处。简化将不胜感激。 所有例子都展示了完全相反的情况:[例如。 1]:id的逻辑是在外部作用域,必须在外部声明,而不是在do,然后使用let 上面; [前任。 2]:复制粘贴重新声明的变量是极其危险的;使用 let 将明确显示问题; [前任。 3]类似于1:你说你想声明一个接近其用法的变量,但你想把它当作全局变量:因此声明必须在全局范围内。一般来说,使用全局变量是不明智的,除非在模块模式中,即 const 声明的对象。以上是关于为啥 var 不被弃用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Vector 和 HashTable 被广泛认为应该被弃用? [复制]
为啥 Vector 和 HashTable 被广泛认为应该被弃用? [复制]
为啥 std::rel_ops::operators 在 C++20 中会被弃用?
为啥(以及赞成啥)maven-bundle-plugin 的 wrap/bundleall 目标被弃用?