I want to contribute to the question and will perhaps add in the @hkotsubo reply.
I will begin my answer with a question:
Why the code below requires more time to run in the Chrome browser than in a file run by Nodejs, if they both use V8?
console.time('loop');
for (var i = 0; i < 1000000; i += 1) {
// faz nada..
}
console.timeEnd('loop');
The issue of var
in the browsers
<script>
var test = 'teste';
</script>
Declare a variable with var
outside the scope of a function (as an example above), causes it to be assigned to the global object. Is held a bind
from variable to global object (window
) and this process is costly in terms of executing the code in the browser. Already give us a hint of why in your code, the this.a
returns to us 2
in the browser, because the var a = 2;
has been declared outside the scope of operation.
Already give us a clue to answer the question I asked there at the beginning. Keep assigning repeatedly the i
to the global window object (which is extremely populated) every iteration of the loop, affects the execution performance.
The issue of var
in the Nodejs
index.js file:
function foo() {
console.log(this.teste);
}
var teste = 'teste';
foo(); // undefined
When Nodejs was developed, the question of var
has been analyzed so that his browser problems do not recur in the Nodejs environment. Let’s agree that we keep creating functions in each file on the Node to treat the var
the same way we do in browser scripts would look boring. So the behavior of Node differs there.
In Nodejs, declaring any variable outside the scope of any function, links it only to the scope of the module itself (not to the global object). Each file has its own scope, this was thought to prevent a variable from extrapolating the scope of a file. Imagine debugging if you had the problem of extrapolating file variables in Node. This behavior explains why your code when running on Node, it returns undefined
, because the Node does not bind
of the variable var a = 2;
to the global object (global
), it leaves it assigned to the scope of the archive itself, so this.a
is equal global.a
that is undefined
.
To facilitate understanding, imagine that Node treats each file as a self-contained function and that each variable declared with var
, let
or const
is assigned the scope of this function.
Already give us the final clue to answer the question I asked there at the beginning. How the Node will be assigning the i
the scope of the archive itself (sparsely populated), makes it easier and faster to repeat the assignment of i
, which results in best execution performance compared to browser performance.
Observing:
If you declare a variable in a file without using the keyword var
and then assign a value to it, the global object will define a property for that variable. That process essentially transforms it into a globally accessible variable. I strongly do not advise using this method as it is not the proper way to create global variables.
It is also important to note that if you set the directive 'use strict'
(which is not enabled by default), Node will disable implicit global ones and you will likely end up with an error in runtime.
In short
It was understood why the behavior distinguished in both environments?
In the browser:
var
out of function scope is assigned to the object window
.
No Nodejs:
Each file is treated as a separate module (proper file scope)
Object global
is available in all files, but by default var
is not assigned to this object
While in browsers the global scope is the object window
, in nodejs the global scope of a module is the module itself, so when you define a variable in the global scope of your Node.js module, it will be local to this module.
To answer my question
The difference in the process of assigning the i
to the overall object in each execution environment (window
in the browser and the file scope itself in Node) results in different performance.
In my tests, were the following results (outputs on the console):
loop: 2.669ms
loop: 4.543212890625 ms
Run the script here and see the result for the browser.
console.time('loop');
for (var i = 0; i < 1000000; i += 1) {
// faz nada..
}
console.timeEnd('loop');
Then run this same script in Nodejs in a file and see the difference in the results.
References:
Curiosity
When entering the mode REPL Node, it does not apply the file scope issue, so the expected behavior resembles the behavior of browsers.
$ node
Welcome to Node.js v12.19.0.
Type ".help" for more information.
> function foo() {
... console.log(this.teste);
... }
undefined
>
> var teste = 'teste';
undefined
>
> foo(); // teste
teste
undefined
>
The nodejs uses the mode
strict
javascript. This brings some changes related to code optimization.– Danizavtz
@Danizavtz: the answer? :)
– Sergio
You can send @Sergio I won’t be able
– Danizavtz
I can complement with an answer just below, if there is something missing to explain
– Danizavtz
Strict mode is enabled by default? if yes, it was not meant to error when it declares the global variable (without var)?
– Thiago