nolan
nolan

Reputation: 467

Why print this value in javascript closure?

I know some closure mechanism, but this code confuses me.

I can understand why num value in message:1 is printed because of unmount's stale closure

but why num value: 5 is printed instead of num value: 1? Isn't num also stale in unmount closure?

const test = () => {
  let num = 0;

  const effect = () => {
    num += 1;
    const message = `num value in message:${num}`;

    return function unmount() {
      console.log(message);
      console.log("num value:", num);
    };
  };

  return effect;
};
const add = test();
const unmount = add();
add();
add();
add();
add();
unmount(); // num value in message:1 ; num value: 5

codesandbox

Upvotes: 2

Views: 103

Answers (1)

Snow
Snow

Reputation: 4097

Isn't num also stale in unmount closure?

No, because only one num is ever created, right here:

let num = 0;

when test runs, and test only runs once.

Any references to num will refer to that one variable. When the effect runs, num += 1; will increment that one variable.

But if you created a new variable inside effect instead of incrementing the outer one, it would be stale.

const test = () => {
  let num = 0;

  const effect = () => {
    const innerNum = num + 1;
    const message = `num value in message:${innerNum}`;

    return function unmount() {
      console.log(message);
      console.log("num value:", innerNum);
    };
  };

  return effect;
};
const add = test();
const unmount = add();
add();
add();
add();
add();
unmount(); // num value in message:1 ; num value: 5

The message is "stale" because that string that's created and used is created before the num has finished being incremented by all the add calls. If you got unmount from the last add, it wouldn't be stale.

const test = () => {
  let num = 0;

  const effect = () => {
    num += 1;
    const message = `num value in message:${num}`;

    return function unmount() {
      console.log(message);
      console.log("num value:", num);
    };
  };

  return effect;
};
const add = test();
add();
add();
add();
add();
const unmount = add();
unmount();

Upvotes: 3

Related Questions