1

I heard that every function remembers(?) the lexical environment where the function had created.

In this code, The function function () { console.log(i);}, I want to know where this function had been created. If some function is a parameter of other function, where is the created(?)/generated point?

function countSeconds(howMany) {
  for (var i =1; i <= howMany; i++) {
    setTimeout(function () {
      console.log(i);
    }, i * 1000 );
  }
};
jaibalaji
  • 3,159
  • 2
  • 15
  • 28
  • It's a function expression. It's created when the argument list of `setTimeout` is evaluated. – Bergi Aug 15 '20 at 21:28
  • @Andreas You're confusing the lexical environment (that indeed *all* closures inherit) with the *thisValue* that only arrow functions inherit from their scope – Bergi Aug 15 '20 at 21:30

3 Answers3

2

In this code, The function function () { console.log(i);}, I want to know where this function had been created.

This function is defined as a function expression. Such an expression is evaluated at runtime, much like an expression { y: x*x } would be evaluated at runtime. But in this case the evaluation result is a function object. And that function is then passed as argument to setTimeout. This means there are just as many functions created as there are iterations of your for loop.

Now, even though the function expression is evaluated at the moment setTimeout is executed, this does not mean that the body of the function is executed at that same time. It is not. It will only be executed when the timeout expires. At that time the function body executes, and at that time only it will evaluate expressions used in that code, such as variable i. In your example, the variable i will already have reached the value howMany+1, because that for loop already ran to completion before the timer expired, and the callback got called.

If that is something you want to avoid, then use a separate variable i for each iteration of the for loop. With let instead of var you create such distinct variables, which only live inside the for loop's block. And so then each of the function expressions will reference its "own" i:

function countSeconds(howMany) {
  for (let i =1; i <= howMany; i++) {
    setTimeout(function () {
      console.log(i);
    }, i * 1000 );
  }
};

countSeconds(10);
trincot
  • 317,000
  • 35
  • 244
  • 286
0

If some function is a parameter of other function, where is the created(?)/generated point?

Like all arguments to a function call, they're evaluated right before the function is called. You can rewrite this with two temporary variables into the equivalent

function countSeconds(howMany) {
  for (var i=1; i<=howMany; i++) {
    const __arg1 = function() {
      console.log(i);
    };
    const __arg2 = i * 1000;
    setTimeout(__arg1, __arg2);
  }
}

The function is created when the function expression is evaluated.

(Also notice that this code has the famous closure in a loop problem.)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
-1

I dont understand what you mean?

You mean where the function console.log() ist defined?

class console {
   log(text) {
     [I dont know]
   }
}

Then you can make "console.log()" to call the function "Log" from Claas console? Did you mean that?

BPP-DEV
  • 21
  • 6
  • Don't post questions in the answer section. Once you have the required reputation you can ask questions to the asker in the comment section. – trincot Jul 01 '23 at 08:50