Есть какие-нибудь примеры нетривиального и полезного примера ключевого слова 'with'?

StackOverflow https://stackoverflow.com/questions/1675982

  •  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 этого не обнаруживает).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top