2015-01-20

Маленькие javascript-ости: array wrapper

Есть два способа перебрать элементы обычного массива:
for(var i=0; i<a.length; i++){ var e=a[i]; do_something_with(e); }
for(var i in a){ var e=a[i]; do_something_with(e); }
Хотя второй выглядит короче, первый считается быстрее. Если мы возьмем ассоциативный массив, то первый метод неприменим, а второй продолжает работать.

Javascript - идеальный язык для определения всяких wrappers = оберток. Определим такую обертку для массива:
function array_wrap(a){
  return {
    a: a,
    fill: function(n, f){
      for(var i=0; i<n; i++) this.a.push(f(i));
      return this;
      },
    foreach: function(f){
      for(var i=0; i<this.a.length; i++){ var e=this.a[i]; f(i,e); }
      return this;
      }
    }
  }

Тогда мы можем написать вчерашний пример так:
array_wrap([])
  .fill(10, function(i){ return function(){ document.write(i); } } )
  .foreach( function(i, e){ e(); } );
Результат: "0123456789".

На typescript это выглядит еще компактнее:
array_wrap([])
  .fill(10, (i)=>( () => { document.write(i); } ))
  .foreach( (i,e) => { e(); } );

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

Конечно, обертки и вызовы функций требуют дополнительных тактов процессора, но для моих задачек практическая производительность оказывается вполне приемлемой. Подобные методики сейчас довольно популярны и есть надежда, что компиляторы научатся оптимизировать такие конструкции.

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

4 comments:

Anonymous said...

Складывается впечатление, что небольшая прослойка программистов, которые появились в 90-тые (с появлением C++ и Java), у которых мозги сформатировались в стиле ООП - ВЫМЕРЛИ. Я делаю это выод на основании убожества браузеров, которые считаю вершиной программистского искусства.
Если программист имеет мозги объектноориентированные, то интерфейс браузера у него должен быть прозрачным, и интуитивно понятным, как это было в продукции замечательной BORLAND. (Я скучаю по тебе, BORLAND).
Каскадные таблицы описывают свойства тегов, но почему там нельзя прописать и методы. там где мы пишем:

color:red;

почему нельзя написать:

onclick:jsFun;

Для тех программистов, у кого мозги правильно устроены - подобная запись должна быть естественной.

Anonymous said...

Ядро IE4..5 делал гений. (Снимаю шляпу.) А интерфейс - дурак.

Про VML я уже говорил. (Гениальная штука.) Я смог научить IE понимать запись в каскадной таблице типа:

onclick:jsFun;

Ни один другой браузер на подобное не способен.

Вот ещё прикольная вещь:
В любом теге ты можешь написать свой параметр. Так к примеру:



И он появится у этого тега. Но только в IE. Ни один другой браузер таких вольностей не допускает.

Потом этот Гений куда-то подевался, и на его месте в Microsoft дураки работают.

Anonymous said...

Пропал мой спан. Придётся повторить:

(spam myPar="abcd">

Valery Tolkov said...

Параметр и в других браузерах можно написать. Я много раз так делал. Но рекомендуется начинать с "data-": http://www.w3schools.com/tags/att_global_data.asp