let 块语句和等价的 with 语句有啥区别?
Posted
技术标签:
【中文标题】let 块语句和等价的 with 语句有啥区别?【英文标题】:What is the difference between a let block statement and an equivalent with statement?let 块语句和等价的 with 语句有什么区别? 【发布时间】:2011-09-23 00:02:28 【问题描述】:已过时
let 语句的块版本在最终确定之前已从 ES6 中删除,并且已从支持它的浏览器中删除。这个问题现在只具有历史意义。
使用 ECMAScript 6 let
block statement 和使用带有等效对象字面量的 with
语句之间有什么区别吗?
使用let
语句
var x = 10;
let (x = x * 10,
y = x + 5)
console.log("x is " + x + ", y is " + y);
使用with
语句
var x = 10;
with (x: x * 10,
y: x + 5)
console.log("x is " + x + ", y is " + y);
// writes "x is 100, y is 15"
【问题讨论】:
这个问题是为了娱乐,还是您正在认真考虑使用with
进行范围界定?
如果答案最终是“没有区别”,那么我会考虑,但我主要是好奇,因为我预计会有区别,但找不到。
【参考方案1】:
您可以同时使用with
和let
语句来实现相同的目标,但我在这里看到了两个显着差异。最后,let
语句是with
语句的新版本,去掉了后者的缺点。
性能:在with
语句的情况下,您将额外的javascript 对象添加到作用域链中。这不是一个小成本,您必须记住对象可能有一个很长的原型链,因此要查找变量,JavaScript 引擎首先必须搜索对象及其所有原型。另一方面,对于let
语句,引擎最多只需要搜索一个附加对象。 let
语句确实可以在没有任何开销的情况下实现,因为在 let
语句中声明的所有变量在编译时都是已知的,并且 JavaScript 引擎可以轻松优化代码,例如通过基本上将您的示例视为:
var x = 10;
var let1x = x * 10;
var let1y = x + 5;
console.log("x is " + let1x + ", y is " + let1y);
代码可读性:正如上面已经提到的,let
语句总是使所有声明在编译时可见,这可以防止这样的代码:
with (foo)
console.log("x is " + x + ", y is " + y);
如果你看上面的代码,x
是什么,y
是什么?它们是对象foo
的函数变量或属性吗?如果不知道foo
是什么,你就无法说出它——而且对于同一函数的不同调用,它可能会有所不同。这是 with
声明已被弃用的主要原因。虽然您可以按照您在问题中所做的方式使用它(这很好),但它也允许非常有问题和不可读的代码结构。 let
声明没有 - 灵活性较低有时是一个优势。
【讨论】:
【参考方案2】:我能想到的最好的办法是with
也会泄漏Object
原型的任何属性:
with (x: 10)
hasOwnProperty = 3;
console.log(hasOwnProperty); // 3
console.log(hasOwnProperty); // [native code]; this is window.hasOwnProperty
在实践中不太可能成为问题,但仍然是一个潜在的问题。
我还怀疑with
比词法稍慢,因为它添加了另一个必须搜索的命名空间。
老实说,我只是避免这两种结构; with
风格的隐式属性访问不适合我,如果我真的需要像这样的紧凑范围,那么带有 let
表达式的裸块比 let
块读起来更尴尬。
【讨论】:
请注意,ECMAScript 5 允许我们创建一个没有原型的对象Object.create(null)
,因此实际上使用它似乎没有副作用。但是,ES5 的严格模式禁用了with
,所以这只能在 ES5 的默认模式下实现,在 ES6 中是不可能的。
请参阅Was there a way to create an object without a prototype prior to ES5? 了解 ES3 的可能(尽管非常不切实际)替代方案。【参考方案3】:
以下是每个语句的不同范围规则。
与:
with 语句使对命名引用的访问效率低下,因为这种访问的范围直到运行时才能计算出来
让:
使用 let 定义的变量的范围是 let 块本身,以及包含在其中的任何内部块,除非这些块以相同的名称定义变量。
let
语句是非标准的,而with
语句在严格模式下不可用。
参考文献
ECMA-327:ECMAScript 3rd Edition Compact Profile (pdf) Resurrecting the with Statement ECMAScript Harmony: Object Extension Literal let: block scoping ECMAScript-6 Draft【讨论】:
以上是关于let 块语句和等价的 with 语句有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章