forEach is a handy loop. However, it is a tricky bugger too. Two things can happen:

  • this is undefined inside the closure function()
  • the return statement doesn't exit the main function

I'd never really considered the nuances of closures until I started using forEach loops in object-oriented JavaScript.

Defining a method in a JavaScript class is done using a prototype. this is required to reference other methods and properties in the class. It's often necessary to loop over an array property, forEach is a handy construct but it requires a closure. this inside a closure refers to the closure itself. Therefore the properties of the class are inaccessible. For instance this code results in an error because this.fileNameStartingWithA is undefined.

const fs = require('fs');
const util = require('util');

function DirUtil(dir) {
  this.dir = dir || ".";
  this.fileNames = fs.readdirSync(this.dir);
  this.fileNameStartingWithA = [];
};

DirUtil.prototype.getSubList = function (pattern) {
  this.fileNames.forEach(function (fileName, i) {
    if (pattern.test(fileName)) {
      this.fileNameStartingWithA.push(fileName);
    }
  });
  return this.fileNameStartingWithA;
  };

// expose the classes
module.exports = {
  DirUtil: DirUtil
};

var d = new DirUtil();
console.log(d.getSubList(/^A/));

      this.fileNameStartingWithA.push(fileName);
                                ^

TypeError: Cannot read property 'push' of undefined

To access this inside the closure, you must save a reference to it before it is redefined in the closure. I like to use thing as a temporary variable:

const fs = require('fs');
const util = require('util');

function DirUtil(dir) {
  this.dir = dir || ".";
  this.fileNames = fs.readdirSync(this.dir);
  this.fileNameStartingWithA = [];
};

DirUtil.prototype.getSubList = function (pattern) {
  var thing = this;
  this.fileNames.forEach(function (fileName, i) {
    if (pattern.test(fileName)) {
      thing.fileNameStartingWithA.push(fileName);
    }
  });
  return thing.fileNameStartingWithA;
  };

// expose the classes
module.exports = {
  DirUtil: DirUtil
};

var d = new DirUtil();
console.log(d.getSubList(/^A/));
[ 'Applications', 'Applications (Parallels)' ]