Pull to refresh

Обход массива в javascript

Reading time2 min
Views1.1K
Пробежать по элементам массива, выбрать из него некоторые элементы или сформировать новый массив необходимо довольно часто. Это можно сделать классическим способом:

var arr=[1,2,3,4,5,6,7]
var map=[];
var subarray=[];
for(var i=0,len=arr.length;i&ltlen;i++){
  var item = arr[i];
  //do something
  alert(item);
  //map and sub
  if(/*some condition*/){
    map.push(item +1);
    subarray.push(item)
  }
}


Однако в ECMA-262 [1] и большинстве фрэймворков поддержаны альтернативные (более элегантные) способы для достижения этой цели:
var arr=[1,2,3,4,5,6,7]
arr.forEach(function((element, index, array){ alert (element); })
var map= arr.map(function((element, index, array){
  if(/*some condition*/)
    return element;
})
var subarray=arr.filter(function((element, index, array){ return  /*some condition*/})


Вы вызываете методы массива передавая им функцию (closure, замыкание, lambda) которая будет вызвана для каждого элемента массива с параметрами (element /* элемент массива*/, index /* индекс этого элемента*/, array /*сам массив*/). В случае функций map и filter создаются новые массивы, которые будут заполнены тем, что возвращает функция (в случае map) или теми элементами над которыми функция вернула true (в случае filter).

Вторым параметром в эти функции можно передать thisObject объект который будет скрыватся за this внутри функции при ее выполнении) [1]:
var writer = {
  sb:[],
  write:    function (s) {
    this.sb.push(s);
  },
  writeln:  function (s) {
    this.write(s + "\n");
  },
  toString: function () {
     return this.sb.join("");
  }
};

[2, 5, 9].forEach(writer.writeln, writer);
print(writer.toString()); // assumes print is already defined

В случае если браузер не поддерживает эти функции их можно определить самомтоятельно [2]:
if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i &lt len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i &lt len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}
if (!Array.prototype.map)
{
  Array.prototype.map = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i &lt len; i++)
    {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

    return res;
  };
}

Среди фрэймворков самая граммотная поддержка этих функций сделана в dojo. Где названия функций совпадают со спецификацией и переопределяются если не поддержаны. В остальных (Ext, jquery, prototype) эти функции тоже поддержаны под другими именами и с разными вариациями.
Tags:
Hubs:
Total votes 15: ↑6 and ↓9-3
Comments20

Articles