Running with Node.js - JavaScript

  1. What is the expected behavior?
    Answer: cleanup.js does not run because the uncaught error makes the first command exit unsuccessfully. When you see a question combining shell operators with Node.js processes, think about two separate layers: how the shell controls command execution, and how Node.js handles runtime errors. In a POSIX shell, && is a logical AND operator that chains commands conditionally — the second command only runs if the first exits with a status code of 0 (success). When bad.js throws an uncaught error, Node.js catches it at the process level and exits with a non-zero status code (typically 1), signaling failure to the shell. The shell sees that failure and skips node cleanup.js entirely. That's why B is correct: cleanup.js never runs because the first command exits unsuccessfully. A is wrong because it confuses loading with executing. Node does finish parsing and loading bad.js, but the uncaught runtime error still causes a non-zero exit — which is all the shell cares about. The internal loading sequence is irrelevant here. C describes a fundamentally incorrect model. The && operator is a shell construct, not a JavaScript feature. It has no concept of "joining" JavaScript files within a single Node process. Each node call spawns a completely separate process. D is simply false. POSIX shells allow multiple Node.js processes to run in the same terminal session — sequentially, in the background, or even in parallel. There's no such restriction. A good rule of thumb: whenever you see shell operators like &&, ||, or ;, ask yourself what exit code the preceding command produces — that's what drives the shell's decision.
  2. Which outcome should be expected?
    Answer: Node prints loaded, reports a ReferenceError, and does not print finished. When you see a question about runtime errors in JavaScript, think about when the JavaScript engine actually encounters a problem — during parsing, or during execution? Node.js (and browsers) execute JavaScript line by line at runtime. When node task.js runs, it first parses the file for syntax errors, but it does not pre-check whether variables or functions exist — that only gets discovered when execution reaches that line. So the engine runs console.log("loaded") successfully, then hits runTask(). Since runTask was never defined, the engine throws a ReferenceError immediately. Because this error is unhandled, execution halts right there — console.log("finished") is never reached. That makes C the correct answer. A is wrong because it implies execution completes normally and the error appears afterward. That's not how unhandled ReferenceErrors work — they crash execution at the point they occur, not after. B reflects a common misconception: that JavaScript "scans ahead" and refuses to run if something looks wrong. Parsing only catches syntax errors (like a missing bracket). An undefined variable is a runtime error — invisible until that line executes. D is simply false. Node.js has no mechanism to delegate an undefined function call to the shell. It strictly interprets JavaScript; unknown identifiers throw ReferenceError, full stop. A useful pattern to remember: syntax errors stop execution before it starts; reference/type errors stop it mid-run. Whenever a question involves an undefined identifier, ask yourself which line the engine is on when it discovers the problem — that line is where execution ends.
  3. Why does this not run report.js in the same way as entering node report.js at the terminal prompt?
    Answer: The interactive prompt treats node report.js as JavaScript source rather than as a shell command. When working with Node.js, it's crucial to understand the difference between two separate environments: your operating system's terminal shell and Node's interactive REPL (Read-Eval-Print Loop). Questions like this test whether you know which environment is actually interpreting your input. When you launch Node by typing node with no arguments, you enter the REPL — a JavaScript runtime that reads and evaluates JavaScript code, not shell commands. So when Priya types node report.js at the > prompt, Node doesn't see a command to launch a new process; it sees a JavaScript expression. Specifically, it reads node as a variable name and report.js as a property access attempt — meaningless JavaScript that won't execute a file. That's exactly why A is correct: the REPL interprets the input as JavaScript source, not as a terminal instruction. B is wrong because the REPL doesn't accept shell commands at all — the file extension is completely irrelevant here. C is wrong because no "second entry" behavior exists in the REPL; this is an invented distractor. D is wrong because directory searching isn't the issue — the REPL simply never attempts to locate or run a file from any directory. A useful mental model: think of the terminal shell and the Node REPL as two different "languages." The shell understands commands like node report.js; the REPL understands JavaScript expressions. Mixing them up is a common beginner mistake. When you see questions about unexpected REPL behavior, ask yourself: is this input valid JavaScript, or is it a shell command?
  4. What is the expected result of the second command?
    Answer: Node fails because it looks for /home/lee/project/src/src/app.js, which does not exist. When running a Node.js script, the path you provide is resolved relative to your current working directory (CWD) — not relative to the project root, not relative to the script itself. This is a fundamental concept in how operating systems and runtimes handle file paths. Here's what happens: when Lee is in /home/lee/project and runs node src/app.js, Node looks for /home/lee/project/src/app.js — which exists, so it works. But after changing into /home/lee/project/src, that same command node src/app.js now resolves relative to the new CWD, pointing to /home/lee/project/src/src/app.js. That path doesn't exist, so Node throws an error. That makes B the correct answer. A is wrong because Node does not walk up parent directories searching for scripts — that behavior doesn't exist. If the resolved path isn't found, Node simply fails. C is wrong because there's no such concept as a "project root" in Node's path resolution. Node has no awareness of your project's structure; it only knows your CWD. D is wrong because Node absolutely accepts relative paths for script execution — the problem here isn't the path style, it's that the relative path resolves to the wrong location given the new CWD. A helpful tip: whenever you see a question about file or module resolution in Node, always ask yourself "what is the current working directory?" That's the anchor point. Relative paths follow the CWD, and changing directories changes everything downstream.
  5. Which explanation and remedy are most accurate?
    Answer: File-system relative paths resolve from the working directory; either run from /work/shop or build the path from the script's own directory. When working with Node.js file paths, the critical distinction is between the working directory (where you launched the node command) and the script's own directory (where the .js file lives). Relative paths like "./config.json" always resolve from the working directory — whichever folder your terminal is sitting in when you run the command. That's exactly why D is correct. When you run node scripts/runner.js from /work/shop, the working directory is /work/shop, so "./config.json" correctly finds /work/shop/config.json. But when you cd into /work/shop/scripts and run node runner.js, the working directory shifts to /work/shop/scripts, and "./config.json" now looks for /work/shop/scripts/config.json — which doesn't exist. The remedy is either to always run from /work/shop, or better yet, build the path dynamically using path.join(__dirname, "../config.json"), which anchors to the script's own directory regardless of where you launch from. A is wrong because Node has no concept of a "project root" derived from a package manifest — package.json does not affect how fs resolves relative paths. B is wrong on its explanation: the issue isn't that paths resolve from the script's directory (they don't — they resolve from the working directory), so moving the file would only be an accidental fix, not an accurate one. C is wrong because Node never changes the working directory after loading a script; that's simply not how Node works. Your study tip: whenever you see fs path issues in Node, immediately ask yourself "where is the terminal, not where is the script?" — and remember __dirname as your portable escape hatch.
  6. How is --trace-warnings interpreted in this invocation?
    Answer: It is a script argument, so the script prints ["--trace-warnings","input.csv"]. When working with process.argv in Node.js, it helps to understand exactly how Node parses a command. Node.js distinguishes between Node-level flags (like --inspect or --max-old-space-size) and script arguments based on position: anything after the script filename is treated as a script argument, period. In the invocation node app.js --trace-warnings input.csv, Node sees app.js as the script to execute. Everything that follows — --trace-warnings and input.csv — is passed directly into the script as arguments. process.argv will be ["node", "app.js", "--trace-warnings", "input.csv"], and after .slice(2), you're left with ["--trace-warnings", "input.csv"]. JSON.stringify then prints exactly that array. So B is correct. A reflects a common misconception: --trace-warnings is a valid Node flag, but only when placed before the script name (e.g., node --trace-warnings app.js). Once Node encounters app.js, it stops looking for its own flags — everything after belongs to the script. C is wrong because Node makes no attempt to validate script arguments as filenames. It simply passes strings through. An argument that looks like a flag causes no error. D is wrong because Node never silently discards arguments. Every token after the script name lands in process.argv. A good rule of thumb: Node flags go before the script; script arguments go after. On exam questions involving process.argv, always trace the exact position of each token relative to the script filename to determine who "owns" it.
  7. Which value does the script print, apart from formatting differences in how arrays are displayed?
    Answer: An array containing only alpha and --mode=test When working with command-line arguments in Node.js, the key object to understand is process.argv — a built-in array that holds every token passed when launching a Node script. It always follows the same structure: index 0 is the path to the Node executable itself, index 1 is the path to the script file being run, and index 2 onward contains the actual arguments you passed on the command line. So when you run node app.js alpha --mode=test, process.argv looks like this: [ '/usr/bin/node', '/path/to/app.js', 'alpha', '--mode=test' ] Calling .slice(2) removes the first two elements (Node and the script path), leaving ['alpha', '--mode=test'] — which is exactly what gets logged. That makes A correct. B is wrong because it assumes slice(2) starts at index 1 (or doesn't slice at all), keeping app.js in the result — but .slice(2) cuts the first two elements, not one. C describes the un-sliced content starting from index 0 — it's what you'd see with process.argv.slice(0, 3), not .slice(2). D is a misconception with no basis in how Node.js works; positional arguments like alpha are not ignored simply because they lack a --flag prefix. Node captures everything after the script name faithfully. A handy mental model: think of process.argv as [node, script, ...yourArgs]. Slicing at 2 is the standard pattern to isolate just your arguments, and you'll see it in virtually every Node CLI tool.
  8. Which statement best explains what happens next?
    Answer: Nothing else appears because the process ended; the file must be run again to produce new output. When you run a Node.js script, you're launching a process — a program that starts, executes its code from top to bottom, and then terminates. Once that process ends, it has no ongoing relationship with the file it came from. The shell returning a prompt is your signal that the process is finished. This is why C is correct. After Mateo runs node status.js and sees version 1, the Node process exits completely. Editing the file afterward has no effect on something that no longer exists. To see version 2, he would need to run node status.js again, starting a brand-new process. A is wrong because Node does not maintain a live connection between a script file and the terminal after execution. Once the process ends, the file and the terminal are completely unrelated — there's nothing "connected" to notice changes. B is wrong because Node does not watch files for changes by default. File watching is an opt-in feature (using tools like nodemon or the --watch flag introduced in newer Node versions). Without explicitly enabling it, Node runs your file once and stops. D is wrong on two counts: terminals don't retroactively remove previous output, and saving a file cannot "invalidate" a process that has already ended. Terminal output is just text printed to the screen — it doesn't get erased when source files change. A useful pattern to remember: process = temporary. Unless you write code that keeps a process alive (like a server), a Node script runs once and exits. Any re-execution requires a new command.
  9. What is the best explanation?
    Answer: The --check option validates syntax without executing the file's program statements. When working with Node.js CLI flags, it's important to understand what each flag actually does to the runtime execution cycle. This question tests whether you know the difference between checking code and running code. The --check flag (also written as -c) is a syntax-only inspection tool. Node.js parses the file and validates that it's syntactically correct JavaScript — but it never enters the execution phase. No statements run, no files are created, no network calls are made. That's exactly why result.txt doesn't appear despite the file being valid: the program was never executed. Answer A correctly captures this behavior. Answer B is wrong because --check doesn't execute the file at all — it doesn't selectively block file operations while allowing other things to run. That kind of sandboxing doesn't exist in this flag's behavior. Answer C is wrong because Node.js doesn't have a mode that only runs exported functions. Exports are a module system concept, not an execution filter. This option invents a behavior that simply doesn't exist. Answer D is wrong because --check is not a "deferred execution" mechanism. Running node prepare.js afterward is a completely separate, independent command — the --check run has no connection to it and sets nothing up for later. A useful mental model: think of --check like a spell-checker for your code. It reads the document and flags grammatical errors, but it doesn't do anything the document describes. Whenever you see questions about Node.js flags, ask yourself: does this flag affect parsing, execution, or output?
  10. Which command supplies the entire path as one entry-file argument?
    Answer: node "daily reports/run.js" When working with shell commands, it's essential to understand how the shell parses arguments versus how the program receives them. The shell splits a command line on whitespace by default, so a directory name with a space — like daily reports — becomes two separate tokens unless you tell the shell to treat them as one. Node.js expects a single file path as its entry-file argument. If the shell splits daily reports/run.js into two tokens, Node sees two arguments instead of one, which breaks the command entirely. The fix is quoting: wrapping a string in double quotes forces the shell to treat everything inside as a single argument, preserving embedded spaces. Option D, node "daily reports/run.js", does exactly this. The quotes tell the shell that daily reports/run.js is one token, so Node receives the complete, correct relative path as a single argument. Option A, node "daily" "reports/run.js", splits the path into two separate quoted strings — daily and reports/run.js. Each becomes its own argument, so Node sees a nonexistent path. Option C, node daily reports/run.js, has no quotes at all, so the shell splits on the space and Node again receives two broken arguments. Option B, "node daily reports/run.js", wraps the entire command, including node itself, in quotes — the shell then tries to find an executable literally named node daily reports/run.js, which doesn't exist. As a study tip, remember: quotes in a shell command protect arguments from being split — they work on the token level, not the whole command line. When a path contains spaces, quote only the path, not the command itself.

Start this quiz