1.4 Hello World
3 Ways to Run JavaScript
There are three main ways to run JavaScript code.
Method 1: Inline Script
Write <script> tags directly inside an HTML file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1 id="greeting">Hello!</h1>
<script>
// Inline JavaScript
console.log("Hello, World!");
// DOM manipulation
const h1 = document.getElementById('greeting');
h1.textContent = 'Hello, JavaScript!';
h1.style.color = 'blue';
</script>
</body>
</html>
Pros: Quick testing without separate files Cons: HTML becomes complex with long code, no caching
Method 2: External Script File
Separate JavaScript code into its own .js file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<h1 id="greeting">Hello!</h1>
<button id="btn">Click me</button>
<!-- Load external script -->
<script src="app.js" defer></script>
</body>
</html>
// app.js
console.log("External script loaded!");
const greeting = document.getElementById('greeting');
const btn = document.getElementById('btn');
btn.addEventListener('click', () => {
greeting.textContent = 'Button clicked!';
});
Pros: Code separation, browser caching, reusable Cons: Additional HTTP request (mitigated by caching)
Method 3: Run with Node.js
Execute with the node command in terminal.
// hello.js
console.log("Hello, World!");
console.log("Node.js version:", process.version);
const name = "JavaScript";
console.log(`Hello, ${name}!`);
# Run
node hello.js
# Output
# Hello, World!
# Node.js version: v20.11.0
# Hello, JavaScript!
<script> Tag Position and defer/async
The position and attributes of <script> tags significantly affect page loading performance.
In <head> (Not recommended)
<head>
<!-- Problem: HTML parsing stops, downloads/executes script, then resumes -->
<!-- DOM not ready yet, so document.getElementById returns null -->
<script src="app.js"></script>
</head>
Just before </body> (Traditional method)
<body>
<!-- HTML content -->
<h1>Hello</h1>
<!-- Runs after DOM is ready -->
<script src="app.js"></script>
</body>
defer attribute (Recommended)
<head>
<!-- Downloads in parallel with HTML parsing, executes after HTML parsing completes -->
<!-- Executes just before DOMContentLoaded event -->
<script src="app.js" defer></script>
</head>
- Doesn't block HTML parsing
- Order guaranteed for multiple scripts
- Runs before
DOMContentLoadedevent
async attribute
<head>
<!-- Downloads in parallel, executes immediately when done (pauses parsing) -->
<script src="analytics.js" async></script>
</head>
- Executes immediately when download completes (briefly pauses HTML parsing)
- Order not guaranteed for multiple scripts
- Best for independent scripts that don't depend on other scripts/DOM
Complete console Methods Guide
console.log('Regular message');
console.info('Info message');
console.warn('Warning message');
console.error('Error message');
console.debug('Debug message');
// Styled output (browser)
console.log('%cStyled text', 'color: blue; font-size: 20px; font-weight: bold');
// Table display
const users = [
{ id: 1, name: 'Alice', score: 85 },
{ id: 2, name: 'Bob', score: 92 },
];
console.table(users);
// Time measurement
console.time('sort time');
const arr = Array.from({ length: 100000 }, () => Math.random());
arr.sort((a, b) => a - b);
console.timeEnd('sort time');
// Grouping
console.group('User Processing');
console.log('Validating name...');
console.log('Validating email...');
console.groupEnd();
// Conditional output
console.assert(1 === 2, '1 and 2 are different');
Hello World with ES Modules
// greet.js
export function greet(name) {
return `Hello, ${name}!`;
}
export const DEFAULT_NAME = 'World';
// main.js
import { greet, DEFAULT_NAME } from './greet.js';
console.log(greet(DEFAULT_NAME)); // Hello, World!
console.log(greet('JavaScript')); // Hello, JavaScript!
<!-- index.html - type="module" required -->
<script type="module" src="main.js"></script>
Pro Tips
Use the Debugger Instead of console.log
// Instead of this
console.log('Value:', someComplexObject);
// This is better: set breakpoint with debugger keyword
debugger; // Execution pauses here when DevTools is open
Remove console in Production
// vite.config.js
export default {
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Remove console.* in production
drop_debugger: true,
},
},
},
};