В чем разница между оператором let block и эквивалентным оператором with?

УСТАРЕЛО

Блочная версия инструкции let была удалена из ES6 до того, как она была завершена, и она была удалена из браузеров, которые ее поддерживали. Этот вопрос сейчас представляет лишь исторический интерес.

Есть ли разница между использованием блока ECMAScript 6 let оператор и используя оператор 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"
}

person Jeremy    schedule 26.06.2011    source источник
comment
Это вопрос для развлечения, или вы серьезно рассматриваете возможность использования with для обзора?   -  person Juan Mendes    schedule 29.06.2011
comment
Если бы ответ был окончательным: никакой разницы, я бы рассмотрел его, но в основном мне было любопытно, потому что я ожидал разницы, но не мог ее найти.   -  person Jeremy    schedule 29.06.2011


Ответы (3)


Лучшее, что я могу придумать, это то, что with также приведет к утечке любого свойства прототипа Object:

with ({x: 10}) {
    hasOwnProperty = 3;
    console.log(hasOwnProperty);  // 3
}
console.log(hasOwnProperty);  // [native code]; this is window.hasOwnProperty

Вряд ли это будет проблемой на практике, но все же потенциальная ошибка.

Я также подозреваю, что with немного медленнее, чем лексические, поскольку добавляет еще одно пространство имен, в котором нужно искать.

Честно говоря, я бы просто избегал обеих конструкций; Неявный доступ к свойствам в стиле with меня не устраивает, и если мне действительно нужна такая узкая область видимости, голый блок с let выражениями внутри читается менее неудобно, чем блок let.

person Eevee    schedule 29.06.2011
comment
Обратите внимание, что ECMAScript 5 позволяет нам создавать объект без прототипа как Object.create(null), поэтому кажется возможным использовать это без побочных эффектов. Однако строгий режим ES5 отключает with, поэтому это возможно только в режиме ES5 по умолчанию и невозможно в ES6. - person Jeremy; 23.08.2011
comment
См. Был ли способ создать объект без прототипа до ES5? для возможной (хотя и очень непрактичной) альтернативы для ЕС3. - person Jeremy; 22.03.2016

Вы можете использовать операторы 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 этого не делает — меньшая гибкость иногда является преимуществом.

person Wladimir Palant    schedule 04.07.2011

Вот различные правила области видимости для каждого утверждения.

с:

оператор with делает доступ к именованным ссылкам неэффективным, потому что области для такого доступа не могут быть вычислены до времени выполнения.

позволять:

Областью действия переменных, определенных с помощью let, является сам блок let, а также любые внутренние блоки, содержащиеся внутри него, если только эти блоки не определяют переменные с теми же именами.

Оператор let нестандартен, а оператор with недоступен в строгом режиме.

Ссылки

person Paul Sweatte    schedule 08.05.2014