JavaScript - MuxiaoWFSkip to main content
This page was machine-translated and may contain errors or omissions. / 本页面为机器翻译,可能存在错漏。
JavaScript

JavaScript

Tue Jun 28 2005
4194 words · 34 minutes

JavaScript

JavaScript script code must be placed inside the <script></script> tags, or you can create a separate .js file and import it via <script src="SomeFile.js"></script>.

Like Java, JS uses semicolons to separate statements.

Basics

Fundamentals

Use the var keyword to define a variable: var a = 0;, var a, b;; a variable defined without the var keyword defaults to a global variable, which can be accessed from anywhere.

You can also declare a variable with let, which is only valid within the code block {} where the let statement is located.

The constant declarator const works the same as in C++.

Function definition: function myFunction(a, b) { return a * b; }, very simple, but note the function keyword in front.

Note: There is a special self-invoking function form, (function () {})(); — function closures solve the counter problem, etc. You can search for it yourself; anyway, I probably won’t use it.

Defining data types isn’t much different from Python — both have dynamic typing (the same variable can be used as different types). The difference is that numbers aren’t distinguished as int or float, but use just number. You can check a variable’s type with the typeof keyword, e.g., typeof a to see the type of variable a.

Note: var myFunction = function (a, b) {return a * b}; var x = myFunction(4, 3); — just like in Python, functions can be assigned directly to a variable and called through the variable.

JS object definitions are also very simple: var person = { name: "Muxiao", hobby: "playing games" };, similar to a dictionary in Python or a HashMap in Java. You can also add object methods inside, defined as: methodName : function() { // code }. For more details, refer to the “Classes” section below.

JS can be called when an HTML event is triggered, but there are many HTML events, with a wide variety of categories. Common ones include mouse events onclick, onmouseover, onmouseout; page events onload, onunload, onchange, onresize, onpagehide, onpageshow; keyboard events onkeydown, onkeyup; form events onsubmit, onreset, onselect.

There are also many string methods, but most have the same syntax as Python.

Various basic statements such as if (condition) { // code } else { // code }, switch (expression) { case value1: // code break; default: // logic code }, for (initialization; condition; increment) { // code }, while (condition) { // code }, do { // code } while (), try { // code } catch (error) { // error handling code } finally { // code }, and so on, will not be elaborated further.

void() is also quite common in other languages; likewise, in JS it simply means it returns no value, but the expression inside the parentheses is still evaluated. The syntax is: void func() and javascript:void func(), or void(func()) and javascript:void(func()).

Therefore, there is a very common statement javascript:void(0), which does nothing and is typically used in a link’s href, e.g., <a href="javascript:void(0)"">Click me</a> means nothing is executed.

Output

JS output can be done via:

  • Using window.alert() to pop up an alert box.
  • Use the document.write() method to write content into the HTML document.(deprecated)
  • Use innerHTML to write into an HTML element.To get an element, you can use the document.getElementById() method.
  • Use console.log() to write to the browser’s console.
<button onclick="showAlert()">window.alert() popup alert box</button>
<button onclick="writeToElement()">innerHTML write to element</button>
<button onclick="writeToConsole()">console.log() write to console</button>
<div id="outputElement" class="output-container">
This is the target element for innerHTML output
</div>
<div id="consoleOutput" class="output-container">
Console output; please check the browser developer tools
</div>
<script>
function showAlert() {
window.alert("This is a message shown via window.alert()!");
}
function writeToElement() {
const element = document.getElementById('outputElement');
element.innerHTML = "<strong>This is content written via innerHTML - " + new Date().toLocaleTimeString() + "</strong>";
}
function writeToConsole() {
console.log("This is content output via console.log() - " + new Date().toLocaleTimeString());
document.getElementById('consoleOutput').innerHTML = "<strong>Message sent to the console; open the developer tools (right-click and inspect) to view it</strong>";
}
</script>

document.getElementById('consoleOutput').innerHTML = "xxx" finds the element whose id is consoleOutput in the page, and then writes content into it.

This is the target element for innerHTML output
Console output; please check the browser developer tools

Classes

A class, i.e., class, is defined as class ClassName { constructor() { // constructor } funcName(){ // normal method } }. Note that methods inside a class are constructed directly with funcName, without the function keyword required outside a class.

Likewise, classes support inheritance:

class ChildClass extends ParentClass {
constructor(/* parameters */) {
super(/* parent class constructor parameters */);
// child class initialization code
}
}

getter and setter:

class MyClass {
constructor(value) {
this._value = value;
}
get value() {
return this._value;
}
set value(newValue) {
this._value = newValue;
}
}
let myClass = new MyClass(42);
// using getter
console.log(myClass.value);
// using setter
myClass.value = 99;

Note: Even though a getter/setter is a method, do not use parentheses when you want to get the property value. The name of a getter/setter method cannot be the same as the property name, and any return inside it is ineffective.

Private: Use # to define private properties and private methods.

class MyClass {
#privateField = 'private field';
getPrivateField() {
return this.#privateField; // only accessible inside the class
}
}

Static methods & properties: Use the static keyword to define static methods or properties. Like Java, static methods or properties cannot access instance properties or instance methods, and must be accessed through the class name.

class MyClass {
static staticMethod() {
// static method
}
static staticProperty = 'static property';
}

Prototype

Every JavaScript object has an internal property [[Prototype]] (usually accessed via __proto__), which points to another object — that object is the prototype. Simply put, the prototype is how objects inherit.

Like Java, all JS objects inherit by default from Object.prototype, which is the prototype of all objects.

We can use the prototype to add methods that weren’t originally in the object:

// add a custom method to all arrays
Array.prototype.customPush = function (element) {
this[this.length] = element;
return this.length;
};
const numbers = [1, 2, 3];
numbers.customPush(4);
console.log(numbers); // [1, 2, 3, 4]
// add a method to all strings
String.prototype.reverse = function () {
return this.split('').reverse().join('');
};
console.log('hello'.reverse()); // 'olleh'

Prototype chain inheritance:

// parent class constructor (non-class form)
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
return `${this.name} made a sound`;
};
// child class constructor
function Dog(name, breed) {
// call parent class constructor
Animal.call(this, name);
this.breed = breed;
}
// set up prototype chain inheritance: Dog's prototype is Animal
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// add child-specific method
Dog.prototype.bark = function () {
return `${this.name} is barking`;
};
// override parent class method
Dog.prototype.speak = function () {
return `${this.name} is speaking`;
};
const dog = new Dog('Wangcai', 'Golden Retriever');
console.log(dog.speak()); // Wangcai is speaking
console.log(dog.bark()); // Wangcai is barking
const animal = new Animal('Animal');
console.log(animal.speak()); // Animal made a sound
//console.log(animal.bark()) // undefined

Above we used the Object.create(proto, propertiesObject) method, which creates an object and sets its prototype to the specified object. proto: the prototype object of the new object (required); propertiesObject: optional parameter, used to add property descriptors to the new object.

// create a prototype object
const person = {
name: 'Zhang San',
age: 25,
introduce: function () {
return `I am ${this.name}, ${this.age} years old`;
}
};
// use Object.create() to create a new object and set the person object as its prototype
const student = Object.create(person);
student.grade = 'Junior';
student.school = 'Tsinghua University';
console.log(student.name); // 'Zhang San' (inherited from prototype)
console.log(student.introduce()); // 'I am Zhang San, 25 years old' (inherited from prototype)
console.log(student.grade); // 'Junior' (own property)

DOM

DOM, the Document Object Model, is the API of the HTML document, used to manipulate the HTML document — that is, it can modify the HTML document.

We already introduced a bit of this in the “Output” section above; here it’s covered in more detail.

You can manipulate HTML elements via JS through the following methods:

  • id: document.getElementById('id')
  • class: document.getElementsByClassName('class')
  • tagName: document.getElementsByTagName('tagName')
  • select all of an element: document.querySelectorAll('element type name')

Note 1: The element obtained with document.getElementsByTagName('tagName') is an HTMLCollection object, so use [0] to get the first element.

Note 2: The element obtained with document.querySelectorAll('element type name') is a NodeList object, so you also need to use [0] to get the first element.

Above we wrote content via innerHTML. JS can also modify attributes: document.getElementById(id).attribute = new attribute value, e.g.: document.getElementById("image").src = "NEW.jpg"; changes the image’s src attribute to NEW.jpg.

Moreover, JS can modify styles: document.getElementById(id).style.property = new property value, e.g.: document.getElementById("ID").style.color = "blue"; changes the text color to blue.

Similarly, in “Fundamentals” we already saw a series of HTML events. Besides calling them directly via events, we can add event listeners to some elements, e.g.: document.getElementById("ID").addEventListener("click", function);Note that here the event listener has no on prefix, and the function has no parentheses.

Having added an event listener, there is naturally also a way to remove it: document.getElementById("ID").removeEventListener("click", function);

You can also use .appendChild(newElement) to add an element: below we add a paragraph.

var para = document.createElement("p");
var node = document.createTextNode("This is a new paragraph.");
para.appendChild(node);
var element = document.getElementById("id");
element.appendChild(para);

Note: There is also .insertBefore(newElement, oldElement) to insert before a certain element; this is omitted here.

Removing an element: To remove an element, you must know its parent element. Below we remove an element:

var parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.removeChild(child);

Replacing an element: Use .replaceChild(newElement, oldElement). Likewise, to replace an element, you also need to know its parent element.

var para = document.createElement("p");
var node = document.createTextNode("This is a new paragraph.");
para.appendChild(node);
var parent = document.getElementById("div1");
var child = document.getElementById("p1");
parent.replaceChild(para, child);

BOM

BOM, the Browser Object Model, is the browser’s API, used to manipulate the browser, for example:

  • Window: window
  • URL: location
  • Screen: screen
  • Browser: navigator
  • History: history

For window, commonly used properties and methods:

  • window.innerHeight - the inner height of the browser window (including the scrollbar)
  • window.innerWidth - the inner width of the browser window (including the scrollbar)
  • window.open() - open a new window
  • window.close() - close the current window Unfortunately, most browsers seem to have restricted this operation
  • window.moveTo() - move the current window Unfortunately, most browsers seem to have restricted this operation
  • window.resizeTo() - resize the current window Unfortunately, most browsers seem to have restricted this operation

location:

  • location.hostname returns the domain name of the web host
  • location.pathname returns the path and filename of the current page
  • location.port returns the port of the web host (80 or 443)
  • location.protocol returns the web protocol used (http: or https:)
  • location.href returns the URL of the current page
  • location.assign(url) loads a new document
  • location.replace(url) replaces the current document

Note: Both location.assign() and location.replace() load a new document, but they differ: location.assign() creates a new window that can be navigated back from, while location.replace() replaces the current window with no back navigation.

screen:

  • screen.availWidth - the available screen width
  • screen.availHeight - the available screen height

navigator:

  • navigator.appName - the browser name
  • navigator.appVersion - the browser version
  • navigator.userAgent - browser information
  • navigator.platform - the operating system running the browser
  • navigator.language - the browser language
  • navigator.cookieEnabled - returns whether the browser has cookies enabled
  • navigator.appCodeName - the browser code name

Note: A navigator’s properties may be changed by the user, so it’s best not to rely on these properties.

history:

  • history.back() - the same as clicking the back button in the browser
  • history.forward() - the same as clicking the forward button in the browser
  • history.go() - when the argument is positive, it goes forward the specified number of pages; when negative, it goes back the specified number of pages; when 0, it refreshes the current page.

Use with caution

There are also various popup dialogs:

// alert box
alert("Warning!");
// confirm box
confirm("Are you sure?");
// prompt box
var x = prompt("Enter your name:", "Harry Potter");

The operation result will be displayed here.

Timing events: setInterval(function, milliseconds) repeatedly executes the specified code at the specified millisecond interval; setTimeout(function, milliseconds) executes the specified code after waiting the specified number of milliseconds. Their counterparts are clearInterval(var) and clearTimeout(var), but what they stop must be a global variable.

// A feature that displays real-time time
const week = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
dom = document.getElementById("dateTxt"),
checkTime = i => (i < 10) ? `0${i}` : i; // add a '0' before numbers less than 10
let today;
function startTime() {
today = new Date();
dom.innerHTML = `Weekday ${week[today.getDay()]}: ${checkTime(today.getHours())}:${checkTime(today.getMinutes())}:${checkTime(today.getSeconds())}`;
}
setInterval(startTime, 500); // loop timing, execute every 500 milliseconds
// A timer feature
const start = new Date();
function timer(start) {
const now = new Date();
const det = now - start;
now.setTime(det);
now.setHours(0);
document.getElementById("id").innerHTML = now.toLocaleTimeString();
}
setInterval(function () {
timer(start)
}, 1000);

You can also create/read Cookies via JS:

// create Cookie; can add expires to set the expiration time
document.cookie = "username=MuxiaoWF";
// read Cookie; returns all cookies as a string
var x = document.cookie;

Since cookies can only be appended at the end, to delete one you can use the expires mentioned above and set a deletion time expires=Thu, 01 Jan 1970 00:00:00 GMT.

Asynchronous

Asynchronous means multi-threading. JS is single-threaded, but can achieve asynchrony through callback functions or Promises.

Callback Functions

Callback functions are further divided into:

  1. Synchronous callback: When the function executes, the synchronous code runs first, then the callback function.
  2. Asynchronous callback: When the function executes, the asynchronous code runs first, then the callback function.
// Array's forEach method uses a synchronous callback
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function (num) {
console.log(num * 2);
});
console.log('This line is output after the callback finishes executing');
// setTimeout is a typical use case for async callbacks
console.log('Start');
setTimeout(function () {
console.log('Executed after 3 seconds');
}, 3000);
console.log('This line executes first');
Synchronous callback
Asynchronous callback

Promise

A Promise is an object in JavaScript used to handle asynchronous operations; it represents a result that will be returned at some point in the future (which may be a success result, or a failure reason).

A Promise has three states:

  • pending: the initial state, neither success nor failure
  • fulfilled: the operation completed successfully
  • rejected: the operation failed

A Promise has several methods:

  1. .then(): the function called when the Promise succeeds.
  2. .catch(): the function called when the Promise fails.
  3. .finally(): the function called when the Promise completes, regardless of success or failure.

Basic usage is as follows:

// create a Promise
const myPromise = new Promise((resolve, reject) => {
// async operation
setTimeout(() => {
const success = true;
if (success) {
resolve('Operation completed successfully');
} else {
reject('Operation failed');
}
}, 1000);
});
// use the Promise
myPromise.then(result => {
console.log(result); // output: operation succeeded
}).catch(error => {
console.log(error); // output: operation failed
}).finally(() => {
console.log('cleanup work');
});

A Promise has several static methods:

.resolve() creates a Promise and resolves it immediately:

const resolvedPromise = Promise.resolve('Success');
resolvedPromise.then(value => {
console.log(value); // output: success
});

.reject() creates a Promise and rejects it immediately:

const rejectedPromise = Promise.reject('Failure');
rejectedPromise.catch(error => {
console.log(error); // output: failure
});

.all() waits for all Promises to resolve or reject:

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
// wait for all Promises to resolve
Promise.all([promise1, promise2, promise3]).then(values => {
console.log(values); // output: [3, 42, "foo"]
});

.race() waits for all Promises to resolve or reject, and returns the result of the first one to resolve or reject:

const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
// return the Promise that finishes first
Promise.race([promise1, promise2]).then(value => {
console.log(value); // output: "two"
});

Promise’s error handling & chained calls: the return value in a chained call is passed to the next chain.

Promise.resolve()
.then(() => {
throw new Error('An error occurred');
})
.catch(error => {
console.log(error.message); // output: error occurred
return 'Recovery value';
})
.then(value => {
console.log(value); // output: recovery value
});

Promises also have limitations:

  1. Cannot be canceled: Once created, a Promise cannot be canceled.
  2. Memory usage: Unhandled Promises may cause memory leaks.
  3. Complex error handling: In complex chained calls, error handling can become complicated.

Example:

// Example 1: Basic Promise
document.getElementById('basicPromise').addEventListener('click', () => {
const resultDiv = document.getElementById('basicResult');
resultDiv.innerHTML = '<div class="loading">Running...</div>';
delay(2000, 'Basic Promise executed successfully!')
.then(result => {
resultDiv.innerHTML = `<div class="success">${result}</div>`;
})
.catch(error => {
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
});
});
// Example 2: Chained calls
document.getElementById('chainPromise').addEventListener('click', () => {
const resultDiv = document.getElementById('chainResult');
resultDiv.innerHTML = '<div class="loading">Running chained calls...</div>';
delay(500, 'Step 1 completed')
.then(result => {
resultDiv.innerHTML = `<div>${result}</div>`;
return delay(500, 'Step 2 completed');
})
.then(result => {
resultDiv.innerHTML = `<div>${result}</div>`;
return delay(500, 'Step 3 completed');
})
.then(result => {
resultDiv.innerHTML = `<div>${result}</div>`;
resultDiv.innerHTML += '<div class="success">All chained calls completed!</div>';
})
.catch(error => {
resultDiv.innerHTML += `<div class="error">Error: ${error.message}</div>`;
});
});
// Example 3: Error handling
document.getElementById('successPromise').addEventListener('click', () => {
const resultDiv = document.getElementById('errorResult');
resultDiv.innerHTML = '<div class="loading">Running success operation...</div>';
delay(1000, 'Operation succeeded!', false)
.then(result => {
resultDiv.innerHTML = `<div class="success">${result}</div>`;
})
.catch(error => {
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
});
});
document.getElementById('errorPromise').addEventListener('click', () => {
const resultDiv = document.getElementById('errorResult');
resultDiv.innerHTML = '<div class="loading">Running failure operation...</div>';
delay(1000, 'Operation failed!', true)
.then(result => {
resultDiv.innerHTML = `<div class="success">${result}</div>`;
})
.catch(error => {
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
});
});
// Example 4: Parallel processing
document.getElementById('parallelPromise').addEventListener('click', () => {
const resultDiv = document.getElementById('parallelResult');
resultDiv.innerHTML = '<div class="loading">Running multiple operations in parallel...</div>';
const promises = [
delay(1000, 'Task A completed'),
delay(2000, 'Task B completed'),
delay(1500, 'Task C completed'),
delay(800, 'Task D completed')
];
Promise.all(promises)
.then(results => {
resultDiv.innerHTML = '<div class="success">All tasks completed:</div>';
results.forEach((result, index) => {
resultDiv.innerHTML += `<div>-${result}</div>`;
});
})
.catch(error => {
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
});
});
// Example 5: Race
document.getElementById('racePromise').addEventListener('click', () => {
const resultDiv = document.getElementById('raceResult');
resultDiv.innerHTML = '<div class="loading">Running race operation...</div>';
const promises = [
delay(2000, 'Slow operation'),
delay(1000, 'Fast operation'),
delay(3000, 'Very slow operation')
];
Promise.race(promises)
.then(result => {
resultDiv.innerHTML = `<div class="success">Finished first: ${result}</div>`;
})
.catch(error => {
resultDiv.innerHTML = `<div class="error">Error: ${error.message}</div>`;
});
});

async/await

async/await is built on top of Promises, making asynchronous code look like synchronous code.

Add the async keyword before a function declaration to indicate the function is asynchronous: async function fetchData() { // function body }.

An async function always returns a Promise: if the return value is not a Promise, it is automatically wrapped into a resolved Promise; if it throws an exception, it returns a rejected Promise.

await can only be used inside an async function: const result = await somePromise; means pausing the execution of the async function to wait for the Promise to complete: if the Promise is resolved, it returns the resolved value; if the Promise is rejected, it throws an error (which can be caught with try/catch).

Example: As we said at the beginning, async/await is built on top of Promises, so anything that can be done with a Promise can also be done with async/await.

// Basic example
document.getElementById('asyncAwaitBasic').addEventListener('click', async () => {
const resultDiv = document.getElementById('asyncAwaitResult');
resultDiv.innerHTML = '<div class="loading">Running async/await operation...</div>';
try {
// use async/await instead of .then()
const step1 = await delay(500, 'Step 1 completed (async/await)');
resultDiv.innerHTML = `<div>${step1}</div>`;
const step2 = await delay(500, 'Step 2 completed (async/await)');
resultDiv.innerHTML += `<div>${step2}</div>`;
const step3 = await delay(500, 'Step 3 completed (async/await)');
resultDiv.innerHTML += `<div>${step3}</div>`;
resultDiv.innerHTML += '<div class="success">async/await all completed!</div>';
} catch (error) {
resultDiv.innerHTML += `<div class="error">Error: ${error.message}</div>`;
}
});

AJAX

AJAX stands for Asynchronous JavaScript And XML (asynchronous JavaScript and XML).

Not writing more — too lazy, nothing much to write about (


Thanks for reading! Follow me if you'd like~

JavaScript

Tue Jun 28 2005
4194 words · 34 minutes
Cover
Sample track
Sample artist
Cover
Sample track
Sample artist
0:00 / 0:00