Есть какие-нибудь примеры нетривиального и полезного примера ключевого слова 'with'?
-
16-09-2019 - |
Вопрос
Я все еще нахожу with
ключевое слово немного...загадочный.
Кратко, with
ведет себя примерно так:
with (obj) {
// do stuff
}
Это добавляет obj
к началу цепочки областей видимости, а затем выполняет with-block.Когда блок закончен, он удаляется obj
от руководителя цепочки поставок.
Согласно MDC, это позволяет вам делать такие вещи, как
var a, x;
var r = 10;
with(Math) {
a = PI * r * r;
x = r * cos(PI / 2);
}
Таким образом, я могу ссылаться на свойства Math
-- как PI
-- прямо, без обиняков Math.PI
.Это прекрасно, но в некотором роде бесполезно.
Кто-нибудь может привести пример интересного использования with
?
Решение
Альтернатива стандартному решению замыкания с использованием функций внутри цикла for:
<a href="#">blah</a><br>
<a href="#">blah</a><br>
<a href="#">foo</a><br>
<script>
(function() {
var anchors = document.getElementsByTagName('a');
for ( var i = anchors.length; i--; ) {
var link = anchors[i];
with ({ number: i }) {
link.onclick = function() {
alert(number);
};
}
}
})();
</script>
Кредит nlogax
за предоставление решения, которое я в значительной степени сорвал:Печально известная проблема с циклом Javascript?
Вот стандартное решение:
<script>
(function() {
var anchors = document.getElementsByTagName('a');
for ( var i = anchors.length; i--; ) {
var link = anchors[i];
(function(i) {
link.onclick = function() {
alert(i)
}
})(i);
}
})();
</script>
Другие советы
Здесь следует сказать, что with
Оператор в JavaScript широко устарел.
См. Дугласа Крокфорда. Заявление считается вредным.
Я не могу сказать это лучше, чем он (серьезно, перейдите по ссылке), но вкратце, если вы сделаете это:
with (mySuperLongObjectReferenceThatIHateTyping) {
propertyAlpha = 'a';
propertyBeta = 2;
propertyGamma = false;
}
Взглянув на этот код, вы не сможете узнать, присваиваете ли вы значения свойствам объекта mySuperLongObjectReferenceThatIHateTyping или глобального объекта (окна).
Крокфорд рекомендует следующее:
var o = mySuperLongObjectReferenceThatIHateTyping;
o.propertyAlpha = 'a';
o.propertyBeta = 2;
o.propertyGamma = false;
Что однозначно.Или вы можете даже использовать функцию, чтобы иметь область действия и не создавать еще одну глобальную переменную:
(function(o) {
o.propertyAlpha = 'a';
o.propertyBeta = 2;
o.propertyGamma = false;
})(mySuperLongObjectReferenceThatIHateTyping);
Микрошаблоны JavaScript Джона Резига показывает интересное использование with.
Я регулярно использую его для добавления нескольких свойств CSS в файл. style
объект, например
with(document.body.style) {
color = 'green';
background = 'red';
}
Кроме того, я использовал его Хотя бы один раз присваивать свойства объекта локальным переменным без необходимости сохранять ссылку на сам объект.
Это также альтернатива замыканиям, когда вы хотите сделать «снимок» значения переменной:
var foo = [];
for(var i = 10; i--;)
with({ i : i }) foo[i] = function() { document.writeln(i); };
// prints 0..9
for(var i = 0; i < foo.length; ++i)
foo[i]();
Имейте в виду, что with
может серьезно повлиять на производительность, поскольку при разрешении любого имени переменной необходимо сначала проверить цепочку прототипов объекта, добавленного в лексическую среду.
Оператор with в JS аналогичен оператору with в say VB.net.Это просто способ избежать повторения со свойствами / методами объекта.
Например, предположим, что элемент управления label изменяется на основе события / действия.Это элемент управления label имеет такие свойства, как FontColor, CssClass, Visibility и т.д.
Вместо того, чтобы программист писал:
myLabel.FontColor=Color.Blue
myLabel.CSSClass="SomeCSSClass"
myLabel.Visiblity=True
myLabel.Text = "Hello World"
Мы можем сократить это до:
With myLabel
.Text = "Hello World"
.FontColor = Color.Blue
.CssClass="SomeCSSClass"
.Visibility=True
End With
У меня нет опыта работы с Javascript, я только начинаю понимать, как, по моему мнению, его следует использовать, поэтому мое мнение не должно иметь такого же веса, как мнение кого-то, кто имеет опыт работы с конкретным языком.Мне было бы интересно услышать отклики на мою идею.
Я экспериментировал со стилем определения классоподобных объектов, который зависит от Javascript с заявление.Я утверждаю, что это законное использование.
Каждый классоподобный объект в этом стиле функционирует как фабрика объектов, удовлетворяющих какой-либо цели.
Этот стиль не использует это ключевое слово в методах экземпляра.
Этот стиль предполагает, что каждый объект, созданный из одного из этих классоподобных объектов, должен иметь публичный аспект и приватный аспект.Объект Javascript представляет каждый из этих аспектов.Владельцы ссылок на объект на самом деле ссылаются только на публичный аспект.Методы, однако, знают оба аспекта, и я реализую это с помощью замыканий.
Я не претендую на то, что этот стиль применим к случаям, когда мы сильно заботимся о времени выполнения или производительности памяти.Я намеренно жертвую немалой частью каждого из них ради эффективности программирования.Я ожидаю найти множество случаев, когда я хочу запрограммировать что-то быстро и с небольшой вероятностью ошибки, и когда требования во время выполнения не будут критичными.
Поскольку я пробовал кодировать в браузере, а не в node.js, практическим соображением среды разработки для меня является то, что синтаксические ошибки в большом исходном файле может быть трудно выявить и исправить.Я решаю эту проблему, добавляя код небольшими порциями.Поэтому я хочу, чтобы классоподобные объекты могли принимать определение метода экземпляра одновременно, вместо того чтобы требовать, чтобы все определения методов отображались в одном исходном файле.
Я изначально объявляю классоподобный объект без каких-либо определенных в нем методов экземпляра и помещаю классоподобный объект в любое пространство имен, в котором я программирую.
Затем я многократно вызываю классоподобный объект с помощью метода в нем под названием "init" и каждый раз передаю инициализатор, функция, вызываемая во время инициализации экземпляра.
В конце концов, когда я начинаю использовать классоподобный объект в качестве фабрики для его экземпляров, всякий раз, когда я запрашиваю у него новый экземпляр, он создает публичный и приватный аспекты для экземпляра, связывает приватный аспект с общедоступным, затем вызывает все определенные инициализаторы, передавая им приватный аспект нового экземпляра.
В моем стиле каждый общедоступный атрибут является методом.Все переменные, значения которых не будут функциями, должны находиться на частной стороне.
Единственное, что может сделать инициализатор, - это установить переменную на частной стороне.
Еще одна вещь, которую может сделать инициализатор, - это добавить метод либо на общедоступной, либо на частной стороне.
Порядок имеет значение для выполнения инициализаторов - классоподобный объект необходим для их выполнения в том же порядке, в котором они определены.Следовательно, каждый инициализатор может рассчитывать на публичные и частные аспекты экземпляра, имеющие атрибуты, которые были установлены более ранними инициализаторами.Для программиста это фактически создает пару лексических областей, поскольку инициализаторы не устанавливаются условным или динамическим кодом любого вида;они устанавливаются по мере того, как исходные файлы выполняются браузером сразу после того, как он их считывает и анализирует.
Теперь в некоторых языках, в частности в языке Ruby и языке Self, вы можете написать голый идентификатор и интерпретировать его как вызов метода для текущего объекта.Таким образом, в Ruby "foo" может означать "self.foo", а в Self "foo" может означать "self foo" (синтаксис вызова метода отличается между этими языками, но вплоть до уровня детализации, на котором я сейчас говорю о семантике, "self.foo" в Ruby и "self foo" в Self одинаковы).Эта аббревиатура, исключающая существование "self", особенно удобна для вызова частных методов и переменных экземпляра.Язык Javascript не обеспечивает такого удобства.
В контекстах внутри метода экземпляра, где я хочу использовать атрибут частной или общедоступной стороны для его значения (обратите внимание, не в левой части присваивания), мне нравится удобство ссылки на атрибут только по его имени и отсутствие необходимости писать "vars." или "self." слева от него, чтобы найти его (я использую "vars" для частного аспекта и "self" для публичного аспекта).По этой причине я оборачиваю каждый инициализатор в Javascript с заявление.Мне это кажется законным, потому что в моем стиле популяция целевого объекта установлена лексически.Чтобы увидеть атрибуты, программисту нужно только взглянуть на инициализаторы, предоставленные ранее в исходных файлах для того же классоподобного объекта (который сам идентифицируется по имени в исходном коде, поэтому для целей разработки программного обеспечения мы можем рассматривать его как лексическую сущность, даже если ни один из анализаторов Javascript этого не обнаруживает).