Комментарии Алана Шторма в ответ на мой ответ относительно with
заявления заставили меня задуматься. Я редко находил причину использовать эту особенность языка и никогда не задумывался над тем, как это может вызвать проблемы. Теперь мне интересно, как я мог бы эффективно использовать ее with
, избегая при этом ее ловушек.
Где вы нашли это with
заявление полезным?
with
так что больше ничего такого нет.Ответы:
Сегодня мне пришло в голову другое использование, поэтому я с энтузиазмом искал в Интернете и нашел упоминание об этом: определение переменных внутри блока .
Фон
JavaScript, несмотря на внешнее сходство с C и C ++, не включает переменные в блок, в котором они определены:
Объявление замыкания в цикле является распространенной задачей, где это может привести к ошибкам:
Поскольку цикл for не вводит новую область видимости, то же самое
num
- со значением2
- будет использоваться всеми тремя функциями.Новая сфера:
let
иwith
С введением
let
оператора в ES6 становится легко вводить новую область, когда необходимо избежать этих проблем:Или даже:
Пока ES6 не станет универсально доступным, это использование будет ограничено новейшими браузерами и разработчиками, желающими использовать транспортеры. Тем не менее, мы можем легко смоделировать это поведение, используя
with
:Цикл теперь работает так, как задумано, создавая три отдельные переменные со значениями от 0 до 2. Обратите внимание, что переменные, объявленные в блоке, не ограничены им, в отличие от поведения блоков в C ++ (в C переменные должны быть объявлены в начале блок, так что в некотором роде это похоже). Это поведение на самом деле очень похоже на
let
блочный синтаксис, представленный в более ранних версиях браузеров Mozilla, но не получил широкого распространения в других местах.источник
for (var i = 0; i < 3; ++i) { setTimeout ((function () { var num = i; return function () { alert (num); }; }) (), 10);}
var toString = function () { return "Hello"; }; with ({"test":1}) { console.log(toString()); };
. В рамках оператора with toString () является унаследованным свойством Object , поэтому явно определенная функция не вызывается. Тем не менее, отличный ответ :-)Я использовал оператор with как простую форму импорта по областям. Допустим, у вас есть какой-то компоновщик разметки. Вместо того чтобы писать:
Вы могли бы вместо этого написать:
Для этого варианта использования я не делаю никаких заданий, поэтому у меня нет проблемы неоднозначности, связанной с этим.
источник
context.bezierCurveTo
сто раз подряд, вы можете сказать,var bc2 = context.bezierCurveTo;
а затем просто идтиbc2(x,x,etc);
каждый раз, когда вы хотите позвонить. Это довольно быстро и даже менее многословно, аwith
супер медленно.Как указывалось в моих предыдущих комментариях, я не думаю, что вы можете использовать
with
безопасно, независимо от того, насколько заманчиво это может быть в любой конкретной ситуации. Поскольку проблема здесь не рассматривается напрямую, я повторю это. Рассмотрим следующий кодБез тщательного изучения этих вызовов функций невозможно определить состояние вашей программы после выполнения этого кода. Если
user.name
уже было установлено, то теперь будетBob
. Если он не был установлен, глобальный объект будетname
инициализирован или изменен на,Bob
иuser
объект останется безname
свойства.Баги случаются. Если вы используете вместе с вами, это в конечном итоге сделает это и увеличит шансы вашей программы не удастся. Хуже того, вы можете столкнуться с рабочим кодом, который устанавливает глобал в блоке with, либо намеренно, либо через автора, не знающего об этой причуде конструкции. Это очень похоже на столкновение с провалом на переключателе, вы не представляете, задумал ли автор это, и нет способа узнать, приведет ли «исправление» кода к регрессии.
Современные языки программирования переполнены функциями. Некоторые функции, после многих лет использования, оказались плохими, и их следует избегать. Javascript's
with
является одним из них.источник
Я на самом деле нашел это
with
заявление невероятно полезным в последнее время. Эта техника никогда не приходила мне в голову, пока я не начал свой текущий проект - консоль командной строки, написанную на JavaScript. Я пытался эмулировать API-интерфейсы консоли Firebug / WebKit, где в консоль можно вводить специальные команды, но они не переопределяют никакие переменные в глобальной области видимости. Я думал об этом, пытаясь преодолеть проблему, о которой упоминал в комментариях к превосходному ответу Shog9 .Чтобы достичь этого эффекта, я использовал два оператора with, чтобы «наслоить» область действия за глобальной областью действия:
Самое замечательное в этом методе заключается в том, что, помимо недостатков производительности, он не страдает от обычных опасений этого
with
утверждения, потому что мы все равно оцениваем в глобальном контексте - нет опасности того, что переменные вне нашего псевдоскопа будут модифицирована.Я был вдохновлен опубликовать этот ответ, когда, к моему удивлению, мне удалось найти ту же технику, что и в других местах - исходный код Chromium !
РЕДАКТИРОВАТЬ: Только что проверил источник Firebug, они соединяют 4 с заявлениями вместе для еще большего количества слоев. Сумасшедший!
источник
Да, да и да. Существует очень законное использование. Смотреть:
В основном любые другие хуки DOM или CSS - фантастическое применение с. Это не значит, что «CloneNode» будет неопределенным и вернется к глобальной области видимости, если вы не пошли своим путем и решили сделать это возможным.
Скорость жалобы Крокфорда заключается в том, что с помощью создается новый контекст. Контексты, как правило, дороги. Согласен. Но если вы только что создали div и у вас нет какой-либо инфраструктуры для настройки вашего css и вам нужно вручную установить около 15 свойств CSS, тогда создание контекста, вероятно, будет дешевле, чем создание переменных и 15 разыменований:
так далее...
источник
with
. Тем не менее, в этом конкретном случае вы могли бы просто сделать:element.style.cssText="background: black ; color: blue ; border: 1px solid green"
extend
метод либо из JQuery или Underscore.js:$.extend(element.style, {fontWeight: 'bold', fontSize: '1.5em', color: '#55d', marginLeft: '2px'})
..css()
метод ...Вы можете определить небольшую вспомогательную функцию, чтобы обеспечить преимущества
with
без двусмысленности:источник
with_
за двойной мутной версии(function(_){ _.a="foo"; })(object_here);
(стандартный способ имитации блоков в стиле c / java). Используйте это вместо этого.Вряд ли это того стоит, так как вы можете делать следующее:
источник
with
.Я никогда не пользуюсь, не вижу причин и не рекомендую это.
Проблема в
with
том, что он предотвращает многочисленные лексические оптимизации , которые может выполнять реализация ECMAScript. Учитывая рост быстрых двигателей на базе JIT, эта проблема, вероятно, станет еще более важной в ближайшем будущем.Может показаться, что это
with
позволяет создавать более чистые конструкции (когда, скажем, вводится новая область вместо обычной обертки анонимной функции или замена многословного псевдонима), но это действительно того не стоит . Помимо снижения производительности, всегда существует опасность присвоения свойству неправильного объекта (когда свойство не найдено в объекте во введенной области видимости) и, возможно, ошибочно вводить глобальные переменные. IIRC, последняя проблема, которая побудила Крокфорда рекомендовать избегатьwith
.источник
with(){}
конструкций, подобных тем, которые приведены в других ответах здесь, в современных браузерах, я бы хотел увидеть их!with(){}
: установка новой области действия сwith
огромными затратами для каждого браузера, который я тестировал. Вы бы хотели избежать этого в любом коде, который вызывается очень часто. Кроме того, Chrome продемонстрировал потрясающий успех для любого кода, выполняемого вwith()
области видимости. Интересно, что IE обладал лучшими характеристиками производительности для кода внутриwith()
блоков: с учетом стоимости установкиwith()
обеспечивает самые быстрые средства доступа к членам в виртуальных машинах IE6 и IE8 (хотя эти виртуальные машины являются самыми медленными в целом). Хорошие вещи, спасибо ...with()
почти в два раза медленнее в Chrome и более чем в два раза быстрее в IE ...!Visual Basic.NET имеет аналогичное
With
утверждение. Один из наиболее распространенных способов, которыми я пользуюсь, - это быстро установить ряд свойств. Вместо:, Я могу написать:
Это не просто вопрос лени. Это также делает для более читабельного кода. И в отличие от JavaScript, он не страдает от двусмысленности, так как все, на что влияет оператор, ставятся перед
.
(точка). Итак, следующие два четко различимы:против
Бывший есть
someObject.Foo
; последний находитсяFoo
в поле зрения снаружиsomeObject
.Я считаю, что отсутствие различий в JavaScript делает его намного менее полезным, чем вариант Visual Basic, так как риск неоднозначности слишком высок. Помимо этого,
with
все еще мощная идея, которая может улучшить читабельность.источник
Ты можешь использовать
with
для представления содержимого объекта в виде локальных переменных для блока, как это делается с помощью этого небольшого шаблонизатора .источник
Использование «с» может сделать ваш код более сухим.
Рассмотрим следующий код:
Вы можете высушить его до следующего:
Я думаю, это зависит от того, предпочитаете ли вы разборчивость или выразительность.
Первый пример более разборчив и, вероятно, рекомендуется для большей части кода. Но большая часть кода в любом случае довольно ручная. Второй вариант немного более неясен, но использует выразительную природу языка для сокращения размера кода и лишних переменных.
Я предполагаю, что люди, которые любят Java или C #, выберут первый путь (object.member), а те, кто предпочитает Ruby или Python, выберут второй.
источник
Я думаю, что очевидное использование в качестве ярлыка. Если вы, например, инициализируете объект, вы просто сохраняете набор «ObjectName». Вроде как "с-слоты" Лиспа, который позволяет вам писать
что то же самое, что писать
Более понятно, почему это ярлык, чем когда ваш язык разрешает «Objectname.foo», но все же.
источник
with-slots
вам нужно указать, какие слоты вы используете, тогда какwith
будете использовать любые слоты, которые будут связаны во время выполнения.Имея опыт работы с Delphi, я бы сказал, что с помощью должно быть последней мерой оптимизации размера, возможно, выполняемой неким алгоритмом минимизатора JavaScript, имеющим доступ к статическому анализу кода для проверки его безопасности.
Проблемы с областями видимости, с которыми вы можете столкнуться при свободном использовании оператора with, могут быть непростой задачей в a **, и я бы не хотел, чтобы кто-либо испытывал сеанс отладки, чтобы выяснить, что он ... происходит в вашем коде только для того, чтобы узнать, что он захватил член объекта или неправильную локальную переменную вместо вашей глобальной или внешней переменной области действия, которую вы намеревались.
VB с утверждением лучше, так как ему нужны точки для устранения неоднозначности, но Delphi с утверждением - это заряженное ружье с hairtrigger, и мне кажется, что javascript один достаточно похож, чтобы оправдать то же предупреждение.
источник
Использование с не рекомендуется, и запрещено в строгом режиме ECMAScript 5. Рекомендуемая альтернатива - назначить объект, свойства которого вы хотите получить доступ к временной переменной.
Источник: Mozilla.org
источник
Оператор with может использоваться для уменьшения размера кода или для закрытых членов класса, например:
Оператор with очень полезен, если вы хотите изменить область, что необходимо для того, чтобы иметь собственную глобальную область, которой вы можете манипулировать во время выполнения. Вы можете использовать константы или некоторые часто используемые вспомогательные функции, такие как, например, «toUpper», «toLower» или «isNumber», «clipNumber» aso ..
О плохой производительности, которую я часто читал: определение области действия не окажет никакого влияния на производительность, фактически в моем FF функция с областью видимости работает быстрее, чем с незаданной областью:
Таким образом, в вышеупомянутом способе оператор with не оказывает негативного влияния на производительность, но хорошо, поскольку уменьшает размер кода, что влияет на использование памяти на мобильных устройствах.
источник
Использование with также делает ваш код медленным во многих реализациях, так как теперь все упаковано в дополнительную область для поиска. Там нет законных оснований для использования с в JavaScript.
источник
var obj={a:0,b:0,c:0};var d=+new Date;with(obj){for(var i=0;i<1000000;++i){a+=1;b+=1;c+=1}}+new Date-d;
дает в среднем 2500, в то время какvar obj={a:0,b:0,c:0};var d=+new Date;for(var i=0;i<1000000;++i){obj.a+=1;obj.b+=1;obj.c+=1}+new Date-d;
в среднем 750, что делает использование более 3 раз медленнее.with
кода и 903 без. С этой крошечной разницей даже в тесном цикле я бы сделал выбор, основываясь на простоте кодирования и простоте рефакторинга в каждом конкретном случае, прежде чем беспокоиться о производительности.Я думаю, что оператор with может пригодиться при преобразовании языка шаблонов в JavaScript. Например JST в base2 , но я видел это чаще.
Я согласен, что это можно запрограммировать без утверждения with. Но поскольку это не создает проблем, это законное использование.
источник
Это хорошо для помещения кода, который выполняется в относительно сложной среде, в контейнер: я использую его для создания локальной привязки для «окна» и для запуска кода, предназначенного для веб-браузера.
источник
Я думаю, что использование литерала объекта интересно, как замена вставки для использования замыкания
или с оператором, эквивалентным замыканию
Я думаю, что реальный риск заключается в случайном минимизации переменных, которые не являются частью оператора with, и именно поэтому мне нравится объектный литерал, передаваемый в, вы можете точно видеть, что это будет в добавленном контексте в коде.
источник
Я создал функцию «слияния», которая устраняет эту двусмысленность с помощью
with
выражения:Я могу использовать его аналогично
with
, но я могу знать, что это не повлияет на область, на которую я не собираюсь влиять.Применение:
источник
Для некоторых коротких фрагментов кода я хотел бы использовать тригонометрические функции, такие как
sin
иcos
т. Д., В режиме степени, а не в режиме излучения. Для этого я используюAngularDegree
объект:Затем я могу использовать тригонометрические функции в режиме степени без дальнейшего языкового шума в
with
блоке:Это означает: я использую объект как набор функций, которые я включаю в ограниченной области кода для прямого доступа. Я считаю это полезным.
источник
with
оператор таким образом, он просто затрудняет чтение кода, потому что вы не знаете, какая функция является глобальной и какая функция вызывается в области действия объекта, поэтому, если какая-либо функция каким-либо образом не определена в тогда объект будет пытаться получить к нему доступ в глобальном пространстве именz = Math.atan2( Math.sin(d * Math.PI / 180), Math.cos( pol.lat * Math.PI / 180) * Math.tan( pos.lat * Math.PI / 180 ) - Math.sin( pol.lat * Math.PI / 180 ) * Math.cos( d * Math.PI / 180) ) * 180 / Math.PI;
даст тот же результат, но это ужас.with
, как это вас озадачило.Я думаю, что полезность
with
может зависеть от того, насколько хорошо написан ваш код. Например, если вы пишете код, который выглядит так:тогда вы можете утверждать, что
with
это улучшит читабельность кода, выполнив это:И наоборот, можно утверждать, что вы нарушаете закон Деметры , но, опять же, возможно, нет. Я отвлекся =).
Прежде всего, знайте, что Дуглас Крокфорд рекомендует не использовать
with
. Я призываю вас проверить его пост в блоге относительноwith
его альтернатив здесь .источник
Я просто не понимаю, как использовать with легче для чтения, чем просто набирать object.member. Я не думаю, что это менее читабельно, но я не думаю, что это также более читабельно.
Как сказал lassevk, я определенно вижу, что использование with будет более подвержено ошибкам, чем просто использование очень явного синтаксиса "object.member".
источник
Вы должны увидеть подтверждение формы в javascript в W3schools http://www.w3schools.com/js/js_form_validation.asp, где форма объекта «сканируется», чтобы найти вход с именем «email»
Но я изменил его, чтобы получить из ЛЮБОЙ формы все поля проверки как не пустые, независимо от имени или количества поля в форме. Ну, я проверял только текстовые поля.
Но с помощью () все стало проще. Вот код:
источник
В Coco- вилке CoffeeScript есть
with
ключевое слово, но оно просто устанавливаетthis
(также доступный для записи, как@
в CoffeeScript / Coco) целевой объект в блоке. Это устраняет неоднозначность и обеспечивает строгое соблюдение режима ES5:источник
Вот хорошее использование для
with
: добавления новых элементов в Object Literal на основе значений, хранящихся в этом Object. Вот пример, который я только что использовал сегодня:У меня был набор возможных плиток (с отверстиями вверху, внизу, влево или вправо), которые можно было использовать, и я хотел быстро добавить список плиток, которые всегда будут помещаться и блокироваться в начале игры. , Я не хотел продолжать печатать
types.tbr
для каждого типа в списке, поэтому я просто использовалwith
.источник
Вы можете использовать с, чтобы избежать необходимости явно управлять арностью при использовании require.js:
Реализация requirejs.declare:
источник
Как отметил Энди Э. в комментариях к ответу Shog9, это потенциально неожиданное поведение возникает при использовании
with
с литералом объекта:Не то неожиданное поведение уже не было отличительной чертой
with
.Если вы все еще хотите использовать эту технику, по крайней мере, используйте объект с нулевым прототипом.
Но это будет работать только в ES5 +. Также не используйте
with
.источник
Я работаю над проектом, который позволит пользователям загружать код для изменения поведения частей приложения. В этом сценарии я использовал
with
предложение, чтобы их код не изменял что-либо вне области, с которой я хочу, чтобы они возились. (Упрощенная) часть кода, которую я использую для этого:Этот код (в некоторой степени) гарантирует, что определенный пользователем код не имеет доступа ни к каким объектам глобальной области действия, таким как
window
ни к одной из моих локальных переменных, через замыкание.Как слово для мудрых, мне все еще нужно выполнить статические проверки кода для кода, представленного пользователем, чтобы убедиться, что они не используют другие хитрые способы доступа к глобальной области видимости. Например, следующий определенный пользователем код получает прямой доступ к
window
:источник
мой
сводится к
Можно ли доверять такому некачественному коду? Нет, мы видим, что это было сделано абсолютно нечитаемым. Этот пример неоспоримо доказывает, что нет никакой необходимости с-заявления, если я беру читаемость право;)
источник