Javascript let block语句和等价的with语句之间有什么区别? 过时的

Javascript let block语句和等价的with语句之间有什么区别? 过时的,javascript,language-features,with-statement,let,ecmascript-6,Javascript,Language Features,With Statement,Let,Ecmascript 6,let语句的块版本在最终确定之前已从ES6中删除,并且已从支持它的浏览器中删除。这个问题现在只具有历史意义 使用和使用带有等效对象文字的with语句有什么区别吗 使用let语句 将与语句一起使用 我能想到的最好办法是with也会泄漏对象的任何属性原型: with ({x: 10}) { hasOwnProperty = 3; console.log(hasOwnProperty); // 3 } console.log(hasOwnProperty); // [native

let语句的块版本在最终确定之前已从ES6中删除,并且已从支持它的浏览器中删除。这个问题现在只具有历史意义

使用和使用带有等效对象文字的
with
语句有什么区别吗

使用
let
语句 将
语句一起使用
我能想到的最好办法是
with
也会泄漏
对象的任何属性
原型:

with ({x: 10}) {
    hasOwnProperty = 3;
    console.log(hasOwnProperty);  // 3
}
console.log(hasOwnProperty);  // [native code]; this is window.hasOwnProperty
这在实践中不太可能是个问题,但仍然是一个潜在的问题

我还怀疑
with
比词典稍微慢一点,因为它添加了另一个必须搜索的名称空间


老实说,我只是避免这两种结构<代码>与-风格的隐式属性访问不适合我,如果我真的需要这样一个紧凑的范围,一个内部有
let
表达式的裸块比
let
块读起来更简单。

您可以使用
with
let
语句来实现相同的目标,但我在这里看到两个显著的区别。最后,
let
语句是对
语句的一个新修订,其中
语句消除了后者的缺点

Performance:如果使用
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
语句不会-灵活性较差有时是一个优势。

以下是每个语句的不同范围规则

与:

with语句使对命名引用的访问效率低下,因为在运行时之前无法计算此类访问的作用域

让我们:

使用let定义的变量的范围是let块本身,以及其中包含的任何内部块,除非这些块使用相同的名称定义变量

let
语句是非标准的,而
with
语句在严格模式下不可用

参考资料

  • (pdf)

是娱乐的问题,还是认真考虑使用<代码> <代码>范围?如果答案是“没有区别”的话,我会考虑它,但我主要是好奇,因为我期望有不同但找不到。注意,ECMAScript 5让我们创建一个没有原型的对象作为<代码> Objut.Cube。(null),因此实际上似乎可以在没有副作用的情况下使用它。但是,ES5的严格模式禁用了带有的
,因此这仅在ES5的默认模式下可能,在ES6中不可能。有关ES3的可能替代方案(尽管非常不实用),请参阅。
var x = 10;
var let1x = x * 10;
var let1y = x + 5;
{
    console.log("x is " + let1x + ", y is " + let1y);
}
with (foo)
{
    console.log("x is " + x + ", y is " + y);
}