Search code examples
javascriptjslint

How can I write these functions to use a forEach() statement?


How can write these (working) functions using forEach() methods:

function loadAudioMeterHistory(cell) {
    var peaks = new Array(4);

    for (var i = 0; i < peaks.length; i++) {
        var peak,
            age;

        peak = cell.getAttribute("data-peak-" + i);
        age  = cell.getAttribute("data-age-" + i);

        peaks[i] = new Peak(peak, age);
    }

    return peaks;
}
function setAudioMeterHistory(cell, peaks) {
    for (var i = 0; i < peaks.length; i++) {
        cell.setAttribute("data-peak-" + i, peaks[i].peak);
        cell.setAttribute("data-age-" + i,  peaks[i].age);
    }
}

My attempt was the following:

function loadAudioMeterHistory(cell) {
    "use strict";
    var peaks = new Array(4);

    peaks.forEach(function(item, index) {
        var p = cell.getAttribute("data-peak-" + index);
        var a = cell.getAttribute("data-age-" + index);

        item = new Peak(p, a);
    });

    return peaks;
}
function setAudioMeterHistory(cell, peaks) {
    "use strict";
    peaks.forEach(function(item, index) {
        cell.setAttribute("data-peak-" + index, item.peak);
        cell.setAttribute("data-age-"  + index, item.age);
    });
}

which, behaves differently, in that peaks is never properly created. The savvy javascripter will undoubtedly recognise that I'm attempting to jslint.com my code.

The Peak() method (for brevity's sake) is simply:

function Peak(peak, age) {
    this.peak = peak;
    this.age  = age;
}

What gives?


Solution

  • forEach just iterates over a list but does not return anything. So use map instead and return the newly created object.

    function loadAudioMeterHistory(cell) {
      "use strict";
    
      var peaks = [0, 1, 2, 3].map(function(item, index) {
        var p = cell.getAttribute("data-peak-" + index);
        var a = cell.getAttribute("data-age-" + index);
    
        return new Peak(p, a);
      });
    }
    

    One more problem is peaks is not available outside the scope of loadAudioMeterHistory. So have the function return that which can be passed into the next function call.

    function loadAudioMeterHistory(cell) {
      "use strict";
    
      return [0, 1, 2, 3].map(function(item, index) {
        var p = cell.getAttribute("data-peak-" + index);
        var a = cell.getAttribute("data-age-" + index);
    
        return new Peak(p, a);
      });
    }
    
    function setAudioMeterHistory(cell) {
      "use strict";
    
      var peaks = loadAudioMeterHistory(cell);
    
      peaks.forEach(function(item, index) {
        cell.setAttribute("data-peak-" + index, item.peak);
        cell.setAttribute("data-age-" + index, item.age);
      });
    }