Search code examples
javascriptscopeclosuresthisfactory

Why won't a boolean object property update?


I have an array of objects. Each object has a method that should update a boolean property in the same object called 'found'.

When I call the function, the property does not update. I am not sure why.

I thought that the 'found' property would be accessible but it isn't??

I have created a minimal version of the problem here: https://codepen.io/sspboyd/pen/XWYKMrv?editors=0011

const gen_s = function () { // generate and return the object
  let found = false;

  const change_found = function () {
    found = true;
  };

  const update = function () {
    change_found();
  };

  return {
    change_found,
    found,
    update
  };
};

const s_arr = []; // initialize an array

s_arr.push(gen_s()); // add a new s object to the array

console.log(s_arr[0].found); // returns 'false'

s_arr.forEach((s) => {
  s.update();
});

console.log(s_arr[0].found);


Solution

  • When your change_found function changes the value of found, it's changing the value pointed to by your let found variable, but the object returned by your gen_s function still points to the old value.

    You can fix your code using the 'holder' pattern, like this:

    const gen_s = function () { // generate and return the object
      let foundHolder = {value: false};
    
      const change_found = function () {
        foundHolder.value = true;
      };
    
      const update = function () {
        change_found();
      };
    
      return {
        change_found,
        foundHolder,
        update
      };
    };
    
    const s_arr = []; // initialize an array
    
    s_arr.push(gen_s()); // add a new s object to the array
    
    console.log(s_arr[0].foundHolder.value); // returns 'false'
    
    s_arr.forEach((s) => {
      s.update();
    });
    
    console.log(s_arr[0].foundHolder.value);

    Or even better, use a class:

    class S {
      constructor() { this.found = false; }
      change_found() { this.found = true; }
      update() { this.change_found(); }
    }
    const s_arr = [];
    s_arr.push(new S());
    console.log(s_arr[0].found);
    
    s_arr.forEach(s => s.update());
    console.log(s_arr[0].found);