LINUX.ORG.RU

with. Что там неочевидного?

 ,


0

1

Взялся сейчас за оператор with, но не могу найти нормальной исчерпывающей инфы по нему. Постоянно наталкиваюсь на какие-то беглые поверхностные статейки, где утверждается, что он че-то там неочевидно себя ведет, бла-бла-бла, не рекомендуют. Но, при этом никакой конкретики, а примеры, которые приводяться, не кажутся мне неочевидными, а кажутся, скорей следствием непонимания авторами того, что они пишут и утверждают. Я ща взял, поигрался с ним в консоли, вроде нормально себя ведет, как ожидается. Может кто покажет неочевидные моменты? Хотелось бы разобраться.

Внимание! Вопросы производительности и оптимизации меня в данном случае не интересуют!

Спасибо.

Там было 2 проблемы:

  • В контексте, где используется объект с помощью with ты не видишь содержимое объекта, поэтому увеличивается шанс что-то попутать
  • Производительность. Т.к. компилятор не в курсе, что именно будет подсунуто в твой with во время выполнения, сразу отпадает ряд оптимизаций

Т.е., если на производительность пофиг и если ты всё делаешь аккуратно, то можно пользоваться на здоровье.

anonymous ()
Ответ на: комментарий от anonymous

Да их много, везде почти об этом тараторят. Я, кстати, в англоязычном инете не могу найти норм статью про with, потому как конфликтует c обычным with (разговорным). Ну, например, что тот же Крокфорд о нем пишет

JavaScript has a with statement that was intended to provide a shorthand when accessing the properties of an object. Unfortunately, its results can sometimes be unpredictable, so it should be avoided.

The statement:

with (obj) {
    a = b;
}


does the same thing as:

if (obj.a === undefined) {
    a = obj.b === undefined ? b : obj.b;
} else {
    obj.a = obj.b === undefined ? b : obj.b;
}


So, it is the same as one of these statements:

a = b;
a = obj.b;
obj.a = b;
obj.a = obj.b;

It is not possible to tell from reading the program which of those statements you will get. It can vary from one running of the program to the next. It can even vary while the program is running. If you can't read a program and understand what it is going to do, it is impossible to have confidence that it will correctly do what you want.

Simply by being in the language, the with statement significantly slows down JavaScript processors because it frustrates the lexical binding of variable names. It was well intentioned, but the language would be better if it didn't have it.

anonimous ()
var obj = { a : 666 };
var z = 222;
with (obj) {
    a = 123;
    z = 999;
}
console.log(obj)
console.log(z)

Output, естественно, такой:

{ a: 123 }
999

with просто выносит содержимое объекта на более верхнюю область видимости. В таком виде оператор with не нужен абсолютно.

slyjoeh ★★★ ()
Последнее исправление: slyjoeh (всего исправлений: 1)
Ответ на: комментарий от slyjoeh

И что тут непонятного? Ищется сначала в объекте, затем по прототипам доходит до глобала и объявляет там. Тут все прозрачно, как-раз.

anonimous ()
Ответ на: комментарий от anonimous

Слияние областей видимости - это всегда опасно и бессмысленно. Кроме того, когда в моем примере у obj появится z, придется переписывать кусок с with.

Вобщем, with - это практически всегда гарантированный быдлокод.

slyjoeh ★★★ ()
Последнее исправление: slyjoeh (всего исправлений: 1)
Ответ на: комментарий от anonimous

With это еще одна жемчужина в коллекции js-wtfаков. Сможешь придумать юзкейзы когда выход за область видимости был бы полезен?

bj ()
Ответ на: комментарий от bj

Да там нет никакого выхода за область видимости. Что ты под этим подразумеваешь? Область видимости какая конкретно? Неймспейс объекта или что? Там идет проход по арототипам до глобала.

полезен

Полезно хотя бы тем, что сокращает код. Из невнятной лапши

if(foo.bar.baz.threethousandone==5){foo.bar.baz.threethousandone...}
он превращается во что-то вменяемое.

anonimous ()
Ответ на: комментарий от slyjoeh

Слияние областей видимости

Это что такое?

когда в моем примере у obj появится z, придется переписывать кусок с with

Зачем?

anonimous ()
Ответ на: комментарий от anonimous

Это что такое?

Ну это я так назвал. Когда есть две и более области видимости, а мы взяли их и объединили. Что и делает with.

Зачем?

Потому что ты когда менял значение z внутри with, ты ожидал, что будет меняться тот z, который объявлен перед with. Как только у obj появится поле z, именно оно станет меняться в блоке with.

slyjoeh ★★★ ()
Ответ на: комментарий от bj

js-wtfаков

Да и вообще, имхо, инфа о js-wtfаках сильно преувеличена. Как ни возьмешь разбирать очередной экземпляр js-wtfака (по-мнению Васи П), внезапно оказывается, что дело было не в бабине. Хотя я не эксперт, конечно, могу многого не знать. Можешь кинуть пример какого-нибудь еще js-wtfака? Разберем его, поглядим:)

anonimous ()
Ответ на: комментарий от slyjoeh

Что и делает with.

Он ничего не объединяет. он ищет переменные по цепочкам прототипов.

ты ожидал, что будет меняться тот z, который объявлен перед with

А почему я должен этого ожидать? Потому что не знаю, как работает with? Или по другой какой-то (странной) причине?

anonimous ()
Ответ на: комментарий от anonimous

Проверка займёт больше усилий, чем ты «сэкономил», заюзав with.

x3al ★★★★★ ()
Ответ на: комментарий от anonimous

Что за бред, где ты откопал эту ересь? With ничего не ищет, он добавляет содержимое объекта в текущую область видимости.

slyjoeh ★★★ ()
Ответ на: комментарий от anonimous

Потому что добавляя поле в одном месте, ты получаешь изменение поведения в другом, что есть нелокальное воздействие. Конечно у тебя как у начинающего идеальная память, но большом проекте это ипаные грабли, и тебя просто отмудохают коллеги, после нескольких часов отладки. Если же так и было задумано, например для подмены лукапов в к-л хитрожопом алгоритме, то все почти норм. Проблема в том, что ты не можешь задекларировать способ использования — проще это сделать явно, подстановкой окружения в исполняющий блок, а конструкцию выкинуть нахер из языка. Если хочется тупо меньше нажатий, открывай новый скоп и выноси в объект переменную. Отдельно можно рассмотреть случай с пропажей поля в объекте — внезапно снесенный глобал это та еще замута в расследовании.

arturpub ★★ ()
Ответ на: комментарий от anonimous

Это неочевидное для программиста нелокальное поведение, нарушающее интуитивную семантику оператора.

Оставим в стороне тот факт, что это может быть удобно для реализации.

buddhist ★★★★★ ()

Лучше б женщину себе нашли.

anonymous ()
Ответ на: комментарий от anonimous

А почему я должен этого ожидать?

Потому что такая у with семантика. Если у объекта нету соответствующего поля, то берется переменная с этим именем из внешнего контекста.

Потому что не знаю, как работает with?

Наоборот, потому что знаешь как он работает.

anonymous ()
Ответ на: комментарий от anonimous

Из внешнего и том смысле, что из цепочки прототипов, да.

В том смысле, что из обычной переменной, никак не связанной с этим объектом.

anonymous ()

Взялся сейчас за оператор with,

Возьмись за МПХ, займи руки.

LongLiveUbuntu ★★★★★ ()
Ответ на: комментарий от anonimous

Он не превращает во вменяемое, это раскидывание грабель. Действие with зависит от внешнего скоупа, что делает его полность сломанным.

bj ()
Ответ на: комментарий от anonimous

Wtf в смысле что курили авторы разрабатывая дизайн языка, а не как это работает. С последним как раз пооблем нет.

bj ()

Но, при этом никакой конкретики, а примеры, которые приводяться, не кажутся мне неочевидными, а кажутся, скорей следствием непонимания авторами того, что они пишут и утверждают.

Ты одним предложением раскрыл всю суть джаваскрипта :) Послушаешь порой, какие они там костыли городят, и диву даешься.

yoghurt ★★★★★ ()
Ответ на: комментарий от anonimous

Проблема в том, что ты кукаретик. Пока весёлые изыскания в одном файлике, всё понятно-хорошо.
А как дело дойдёт до большого проекта все эти отсутсвующие точки с запятыми, with, etc. Свалятся на тебя кучей спагетти. И хорошо, если на тебя, а не коллега попросит тебя выйти.

anonymous ()

что он че-то там неочевидно себя ведет, бла-бла-бла

а неявное приведение типов их уже не смущает?

MyTrooName ★★★★★ ()
Ответ на: комментарий от MyTrooName

Да в общем не особо. Я пока не сталкивался с серьезными проблемами. Это удобно, удобство компенсирует. Например, без неявного привидения нам пришлось бы писать

expr.toString()
//или 
String(expr)
//это все затрудняет и замедляет читаемость,
//а так мы пишем
""+expr
А в более сложных случаях, можно избежать целых портянок засчет этого. Но идеально было бы, если бы типов вообще не было, тогда и приводить бы ничего не пришлось.

anonimous ()
Ответ на: комментарий от anonimous

если бы типов вообще не было

ну, пиши на макроассемблере

MyTrooName ★★★★★ ()
Ответ на: комментарий от anonimous
""+expr

работает и в языках со строгой типизацией (джава, питон). toString() применяется автоматом. в сипипишечке тоже не трудно сделать на перегрузках

Проблемы в js начинаются с «123»+«4 июня» итп

MyTrooName ★★★★★ ()
Последнее исправление: MyTrooName (всего исправлений: 3)
Ответ на: комментарий от MyTrooName

начинаются с „123“+„4 июня“ итп

В чем проблема? Даже если 123+«4 июня» никаких проблем нет. А ты конкатенируешь строки и чему то удивляешься. У тебя там и привиденя то нет никакого. Это ваще п-ц.

anonimous ()
Ответ на: комментарий от MyTrooName

работает и в языках со строгой типизацией (джава, питон). toString() применяется автоматом. в сипипишечке тоже не трудно сделать на перегрузках

Проблема не в том, что можно сделать «„+expr, проблема в том, что в динамическом языке это потом может уйти в любую другую ф-ю. А в статическом - не сможет.

anonymous ()
Ответ на: комментарий от anonymous

Все верно, там это на уровне сахара просто, а тут на уровне семантики.

anonimous ()

Из последних Delphi тоже убрали with. У меня с ним проблем не было. Но говорят, что некоторые товарищи у которых неудачно совпали имена чуть не свихнулись при отладке.

Archer73 ()

люди не читают исходник целиком, а только одно конкретное место которое они собираются менять

stevejobs ★★★★☆ ()
Ответ на: комментарий от stevejobs

Ты хочешь сказать что это не так? Я Крокфорда и цитаты из инета не читал, я это эксперементально установил:)

a=10; b=20
ob={a: 1, __proto__: {b: 2}}
with(ob){a=100; b=100}

console.log(ob.a, ob.b, a, b)//100 100 10 20

anonimous ()
Ответ на: комментарий от stevejobs

Просто там глобальная область стоит в конце цепочки, отсюда и непонятки. А вообще, это вполне вписывается в идеологию JS, мы должны обращаться к объекту абстрагируясь от того, является ли свойство в поле самого объекта, или оно унаследовано.

anonimous ()
Ответ на: комментарий от stevejobs

Не, просто ты ответил на сообщение, где оратор утверждал, что я это, якобы придумал. Для него это представляет собой некое волшебное «слияние». А так, вообще, эти фичи взяты из Ъ-OOП, в стиле Кея, так что не надо:) Это, как раз не говно.

anonimous ()
Ответ на: комментарий от anonimous

имхо, наша цель как разработчиков тулзов для программирования - делать их все проще и проще (без уменьшения мощности результатов!), до тех пор, когда каждый первоклассник сможет кодить все что угодно. Может быть, когда-нибудь компьютеры будут программировать себя сами, а люди будут для этого не нужны совсем. Для этого нужно вырабатывать специальные механизмы программирования, и JS, в этом не помогает никак. Наоброт, в нем нужно часто задумываться о вещах, о которых можно было бы уже и не задумываться никогда.

любителям JS в аду будут презентовать такую пытку: им дается проект, который на JS кодили индусы за 2$ в час в течение 5 лет. Весь код там вдоль и поперек написан с помощью with. Около миллиона строк. Программа не запускается. Нужно заставить ее работать, когда заставишь - тебя отпускают в Рай. ....а между тем джависты-ынтерпрайзники такие задачи уже при жизни отлично решают

stevejobs ★★★★☆ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.