10 minutes read

Node.js has predefined global objects that you can access from anywhere in your application. Global objects are a key feature of Node.js as the global scope of JavaScript objects differs between Node.js and browser top-level scope. Global objects in Node.js are useful because they are well-documented, provide standard ways to solve typical problems, and have good support and compatibility with other modules. Using global objects is also convenient as you can use them anywhere without the need for explicit import.

Globality of JavaScript Objects

For example, you could use the console global object that is accessible from the browser and Node.js scope, to write something to the console using the log method of the console global object. Take a look at the following implementation:

console.log('Hello!'); // Hello!

Many objects in Node.js are considered global by default. They can be accessed from any module without the need for requiring (importing) them. Some of these global objects are: String, Array, Math, and Date.

const myString = 'Hello!';
console.log(myString.toUpperCase());
// Output: HELLO!

The example above uses toUpperCase() method on myString. The toUppercase() method belongs to the String global object and can be called without importing or defining the String object.

A proper understanding of the behavior and uses of global objects in Node.js can help you to leverage them effectively.

Node.js vs browser scope

JavaScript top-level scope is the outermost scope of a program or a module where variables and functions are defined without being enclosed in any other scope. However, there are some differences between top-level visibility in Node.js and in the browser.

The browser's top-level scope is usually the global scope. Variables and functions defined in the global scope are attached to the window object, which serves as the global object. It is possible to access these variables and functions using the window object from any part of your code.

Meanwhile, the top-level scope of a module in Node.js is not attached to the global object. For this reason, functions and top-level variables are not bound to the global object and are only available within the module in which they are defined. If you want to avail variables and functions defined in a module to other modules, you have to export them using the module.exports or exports object.

// Node.js module
const nodeVar = 'Hello from Node.js!';

console.log(nodeVar);
// Output: Hello from Node.js!

console.log(global.nodeVar);
// Output: undefined
// Browser script
var browserVar = 'Hello from the browser!';

console.log(browserVar);
// Output: Hello from the browser!

console.log(window.browserVar);
// Output: Hello from the browser!

The two code snippets above show the difference between Node.js and browser top-level scope. nodeVar is defined in the Node.js module and browserVar in the browser script. In Node.js, nodeVar is only accessible within the module where it is defined and not attached to the global object. But in the browser, browserVar is attached to the window object and accessible globally from any part of the code.

It is important to understand the difference between Node.js and browser top-level scope. It can affect how you design and structure your code in a Node.js application.

__dirname and __filename

__dirname and __filename are global Node.js objects. They store information about the current module. These objects can only be used in the Node.js scope and not in the browser. Also, they are particularly useful when you need to specify a relative path to a file or other module based on the directory of the current module. This is because __filename will return the file name and its full path, whereas __dirname will return the absolute path to the directory where the current module is located.

// index.js

console.log(__dirname);
// Output: /Users/username/Documents/projects

console.log(__filename);
// Output: /Users/username/Documents/projects/index.js

In the example shown above, __dirname returns the absolute path of the final directory in which the module is located. And __filename returns the absolute path and name of the current module.

These objects are often useful when you have to work with files. For example, if you want to write to or read something from a file, it is better to get the path to the end file from the current module's absolute path.

global

The global object allows you to access global variables and functions in Node.js applications. It is like the window object in the browser which is only accessible in the top-level scope of the browser. In contrast, the global object is accessible anywhere, anytime, and in any module or function.

You can see what a global object contains by default with this line of code:

console.log(global);

You will get the following result:

<ref *1> Object [global] {
  global: [Circular *1],
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  structuredClone: [Function: structuredClone],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  atob: [Function: atob],
  btoa: [Function: btoa],
  performance: Performance {
    nodeTiming: PerformanceNodeTiming {
      name: 'node',
      entryType: 'node',
      startTime: 0,
      duration: 163.58535599708557,
      nodeStart: 53.69286799430847,
      v8Start: 81.11867100000381,
      bootstrapComplete: 142.5482960343361,
      environment: 119.57464200258255,
      loopStart: 149.81365203857422,
      loopExit: -1,
      idleTime: 0.001684
    },
    timeOrigin: 1680864521746.335
  },
  fetch: [AsyncFunction: fetch]
}

In the result above, you can see that the global object has some familiar functions like setTimeout, setInterval, and fetch. But this is not a complete list of global objects. For example, console is a global object. You can check that by using these two commands:

console.log('Hello');
global.console.log('Hello');

// Output:
// Hello
// Hello

As you can see, the output is similar because the console object is a part of the global object and it is accessible from any part of your code.

global.myVar = "Hello, world!";

console.log(myVar);
// Output: Hello, world!

In the code snippet shown above, the value of the global variable myVar is assigned using the global object. After this, the variable will be available from anywhere in the application. However, it isn't a good idea to store your variables in a global object because your code will become unnecessarily complicated. It is better to use local variables and pass them to functions or use modules to isolate the functionality.

require(), module, and exports

require(), module, and exports are other useful Node.js global objects. You can use them to share functionality between modules.

The require() method can load external modules into your current module by passing the module name or the path of that module. You can then use this object to access the functionality defined in the loaded module.

const fs = require('fs');

fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

In the example above, the require() function loads the built-in fs module. Once loaded, the fs module helps you to work with the file system, read files or write something in it.

The module object contains information about the current module. Like its absolute path, file name, and its export values.

module is not actually a global object. It is essentially a reference to the object of the current module
// math.js module
const add = (x, y) => x + y;
const multiply = (x, y) => x * y;

module.exports = { add, multiply };

In the example above, add and multiply functions are exported from the math.js file so that they can be used in other modules with the help of module.exports. To access add and multiply functions in other modules, you should use the require() function and pass into it the path to the module math.js. Here's how you can use functions using require():

const math = require('./math.js');

console.log(math.add(3, 2)); // 5
console.log(math.multiply(3, 3)); //9

You can also use the shorthand for module.exportsexports. Since this is just a direct link, exports works just like module.exports.

// greetings.js module

exports.sayMeow = () => console.log('Meow!');
exports.sayBark = () => console.log('Bark!');

In Node.js, modules are cached the first time they are accessed. Therefore, if you call that module once in another module, any changes you make to the first module after importing it won't be available. So the Node.js cache stores the module's state that you exported at first.

Conclusion

In summary, __dirname and __filename provide information about the directory and filename of the current module. global is the global object that can be accessed from any part of the code. It allows you to store or read other objects and your variables in the global Node.js scope. You can use require() to load modules and use their exports. Also, you can use module and exports to define and access the exports of a current module.

Global objects play a crucial role in the module system of Node.js. They allow you to create reusable code. Understanding their uses and behavior is essential for developing efficient and effective Node.js applications. You should also consider the difference between Node.js and browser top-level scope when designing Node.js applications.

8 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo