A couple of things are going on here.
One is that when you run a script like node myScript.js, the script is run as a "module". If your package.json has "type": "commonjs", or doesn't specify the "type" field, it is run as a CommonJS module. If your package.json has "type": "module", it is run as a ECMAScript module. (related docs). That is, if you're using .js as a file extension. If you use .cjs, NodeJS will treat it as a CommonJS module, and if you use .mjs, NodeJS will treat it as a ECMAScript module. (related docs).
See also 'this' different between REPL and script. The TL;DR is that with a CommonJS Module, the code in the module is run as if it were wrapped in the following:
var ctx = {};
(function(exports) {
// your code
console.log(this === globalThis); // false
}).call(ctx, ctx);
But if you run NodeJS in REPL mode (just run node in your system console), then this === globalThis is true, and variables declared with var at the "top level scope" will be placed in the globalThis object, just like they are in the browser console (where globalThis is synonymous with the global window object).
In your browser console, you get "hi" because the function where you console.log(this.greeting) is called without being given a specific this, so it falls back to globalThis. But in ECMAScript module contexts (Ex. NodeJS scripts run with a package.json with "type": "module", or web <script module> (module scripts)), the this at the top-level is always undefined.
Another thing is that if you don't specify strict mode, JavaScript will typically be run in "sloppy mode" by default, where this is never undefined. Strict mode is usually opt-in, but in a ECMAScript module context, strict mode is the default. That's why you're getting undefined when running node myScript.js when you'd actually be getting an error if you did something to enable strict mode.
Here's what it would look like "behind the scenes" to run a CommonJS module with strict mode enabled (if you were to put "use strict"; at the top of your script file):
let ctx = {};
(function() {
"use strict";
function a(){
console.log(this.foo);
}
a(); // Uncaught TypeError: Cannot read properties of undefined (reading 'foo')
}).call(ctx);
You'd get the same error running the above code without explicitly using "use strict"; if you put "type": "module" in your package.json.
More readings: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this.