Finished Chap01
parent
05787f658e
commit
5ea4e5c80e
|
@ -17,7 +17,7 @@
|
|||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
"forwardPorts": [3000],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "yarn install",
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
# Chapter 1. Introduction to JavaScript
|
||||
|
||||
* JavaScript is nothing related to Java.
|
||||
* JS has grown from pure scripting-language to a robust general-purpose language (like C, C++)
|
||||
|
||||
JS & host environment:
|
||||
* Core JS defines minimal API (numbers, text, etc).
|
||||
* Input/Output, advanced feature belongs to "host environment" in which JS is embedded. E.g. of host env
|
||||
* Web browser: original host env
|
||||
* Input to JS: mouse click, keyboard
|
||||
* Output from JS: display HTML & CSS
|
||||
* Node: JS can access entire OS, so JS can read/write files as well.
|
||||
|
||||
## 1.1 Exploring JavaScript
|
||||
|
||||
To test JS interactly, methods available:
|
||||
1. JS interpretor in web browser as **web developer tools (F12)**, select **Console**
|
||||
2. Download & Install node.js and type `node` to activate interactive JS session.
|
||||
1. I prefer to use [VSCode Remote Development Container Images for Node.js](https://github.com/microsoft/vscode-dev-containers/tree/master/containers/javascript-node), which can be set directly using `.devcontainer.json` file
|
||||
|
||||
## 1.2 Hello World
|
||||
|
||||
Run JS codes, 2 methods:
|
||||
1. Copy/Paste codes to JS console
|
||||
2. (Docker preference) Save codes to a file `.js`, run file of JavaScript code with Node `node snippet.js`
|
||||
|
||||
## 1.3 A Tour of JS
|
||||
|
||||
Quick introduction to JS using code e.g.
|
||||
|
||||
### Basic syntax
|
||||
|
||||
* Comments
|
||||
* Variable declaration
|
||||
* Assigning value
|
||||
* Data types
|
||||
|
||||
```js
|
||||
// Anything following double slashes is an English-language comment.
|
||||
// Read the comments carefully: they explain the JavaScript code.
|
||||
|
||||
// A variable is a symbolic name for a value.
|
||||
// Variables are declared with the let keyword:
|
||||
let x; // Declare a variable named x.
|
||||
|
||||
// Values can be assigned to variables with an = sign
|
||||
x = 0; // Now the variable x has the value 0
|
||||
x // => 0: A variable evaluates to its value.
|
||||
|
||||
// JavaScript supports several types of values
|
||||
x = 1; // Numbers.
|
||||
x = 0.01; // Numbers can be integers or reals.
|
||||
x = "hello world"; // Strings of text in quotation marks.
|
||||
x = 'JavaScript'; // Single quote marks also delimit strings.
|
||||
x = true; // A Boolean value.
|
||||
x = false; // The other Boolean value.
|
||||
x = null; // Null is a special value that means "no value."
|
||||
x = undefined; // Undefined is another special value like null.
|
||||
```
|
||||
|
||||
* Objects
|
||||
* Arrays
|
||||
|
||||
```js
|
||||
// JavaScript's most important datatype is the object.
|
||||
// An object is a collection of name/value pairs, or a string to value map.
|
||||
let book = { // Objects are enclosed in curly braces.
|
||||
topic: "JavaScript", // The property "topic" has value "JavaScript."
|
||||
edition: 7 // The property "edition" has value 7
|
||||
}; // The curly brace marks the end of the object.
|
||||
|
||||
// Access the properties of an object with . or []:
|
||||
book.topic // => "JavaScript"
|
||||
book["edition"] // => 7: another way to access property values.
|
||||
book.author = "Flanagan"; // Create new properties by assignment.
|
||||
book.contents = {}; // {} is an empty object with no properties.
|
||||
|
||||
// Conditionally access properties with ?. (ES2020):
|
||||
book.contents?.ch01?.sect1 // => undefined: book.contents has no ch01 property.
|
||||
|
||||
// JavaScript also supports arrays (numerically indexed lists) of values:
|
||||
let primes = [2, 3, 5, 7]; // An array of 4 values, delimited with [ and ].
|
||||
primes[0] // => 2: the first element (index 0) of the array.
|
||||
primes.length // => 4: how many elements in the array.
|
||||
primes[primes.length-1] // => 7: the last element of the array.
|
||||
primes[4] = 9; // Add a new element by assignment.
|
||||
primes[4] = 11; // Or alter an existing element by assignment.
|
||||
let empty = []; // [] is an empty array with no elements.
|
||||
empty.length // => 0
|
||||
|
||||
// Arrays and objects can hold other arrays and objects:
|
||||
let points = [ // An array with 2 elements.
|
||||
{x: 0, y: 0}, // Each element is an object.
|
||||
{x: 1, y: 1}
|
||||
];
|
||||
let data = { // An object with 2 properties
|
||||
trial1: [[1,2], [3,4]], // The value of each property is an array.
|
||||
trial2: [[2,3], [4,5]] // The elements of the arrays are arrays.
|
||||
};
|
||||
```
|
||||
|
||||
Comment Syntax in code e.g.
|
||||
* `=>` shows value produced by code
|
||||
* `// !` code on the line throws an exception
|
||||
|
||||
### Expression vs. Statement
|
||||
|
||||
* **Expression** used by JS to evaluate and produce a value, but don't do anything
|
||||
* **Statement** don't have a value but alter the state of program. e.g. variable declaration & assignment statement
|
||||
|
||||
## 1.4 Example: Charater Frequency Histograms
|
||||
|
||||
```js
|
||||
/**
|
||||
* This Node program reads text from standard input, computes the frequency
|
||||
* of each letter in that text, and displays a histogram of the most
|
||||
* frequently used characters. It requires Node 12 or higher to run.
|
||||
*
|
||||
* In a Unix-type environment you can invoke the program like this:
|
||||
* node charfreq.js < corpus.txt
|
||||
*/
|
||||
|
||||
// This class extends Map so that the get() method returns the specified
|
||||
// value instead of null when the key is not in the map
|
||||
class DefaultMap extends Map {
|
||||
constructor(defaultValue) {
|
||||
super(); // Invoke superclass constructor
|
||||
this.defaultValue = defaultValue; // Remember the default value
|
||||
}
|
||||
|
||||
get(key) {
|
||||
if (this.has(key)) { // If the key is already in the map
|
||||
return super.get(key); // return its value from superclass.
|
||||
}
|
||||
else {
|
||||
return this.defaultValue; // Otherwise return the default value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This class computes and displays letter frequency histograms
|
||||
class Histogram {
|
||||
constructor() {
|
||||
this.letterCounts = new DefaultMap(0); // Map from letters to counts
|
||||
this.totalLetters = 0; // How many letters in all
|
||||
}
|
||||
|
||||
// This function updates the histogram with the letters of text.
|
||||
add(text) {
|
||||
// Remove whitespace from the text, and convert to upper case
|
||||
text = text.replace(/\s/g, "").toUpperCase();
|
||||
|
||||
// Now loop through the characters of the text
|
||||
for(let character of text) {
|
||||
let count = this.letterCounts.get(character); // Get old count
|
||||
this.letterCounts.set(character, count+1); // Increment it
|
||||
this.totalLetters++;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the histogram to a string that displays an ASCII graphic
|
||||
toString() {
|
||||
// Convert the Map to an array of [key,value] arrays
|
||||
let entries = [...this.letterCounts];
|
||||
|
||||
// Sort the array by count, then alphabetically
|
||||
entries.sort((a,b) => { // A function to define sort order.
|
||||
if (a[1] === b[1]) { // If the counts are the same
|
||||
return a[0] < b[0] ? -1 : 1; // sort alphabetically.
|
||||
} else { // If the counts differ
|
||||
return b[1] - a[1]; // sort by largest count.
|
||||
}
|
||||
});
|
||||
|
||||
// Convert the counts to percentages
|
||||
for(let entry of entries) {
|
||||
entry[1] = entry[1] / this.totalLetters*100;
|
||||
}
|
||||
|
||||
// Drop any entries less than 1%
|
||||
entries = entries.filter(entry => entry[1] >= 1);
|
||||
|
||||
// Now convert each entry to a line of text
|
||||
let lines = entries.map(
|
||||
([l,n]) => `${l}: ${"#".repeat(Math.round(n))} ${n.toFixed(2)}%`
|
||||
);
|
||||
// And return the concatenated lines, separated by newline characters.
|
||||
return lines.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// This async (Promise-returning) function creates a Histogram object,
|
||||
// asynchronously reads chunks of text from standard input, and adds those chunks to
|
||||
// the histogram. When it reaches the end of the stream, it returns this histogram
|
||||
async function histogramFromStdin() {
|
||||
process.stdin.setEncoding("utf-8"); // Read Unicode strings, not bytes
|
||||
let histogram = new Histogram();
|
||||
for await (let chunk of process.stdin) {
|
||||
histogram.add(chunk);
|
||||
}
|
||||
return histogram;
|
||||
}
|
||||
|
||||
// This one final line of code is the main body of the program.
|
||||
// It makes a Histogram object from standard input, then prints the histogram.
|
||||
histogramFromStdin().then(histogram => { console.log(histogram.toString()); });
|
||||
```
|
||||
|
||||
Running this program using command in Docker `node charfreq.js < charfreq.js`
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* This Node program reads text from standard input, computes the frequency
|
||||
* of each letter in that text, and displays a histogram of the most
|
||||
* frequently used characters. It requires Node 12 or higher to run.
|
||||
*
|
||||
* In a Unix-type environment you can invoke the program like this:
|
||||
* node charfreq.js < corpus.txt
|
||||
*/
|
||||
|
||||
// This class extends Map so that the get() method returns the specified
|
||||
// value instead of null when the key is not in the map
|
||||
class DefaultMap extends Map {
|
||||
constructor(defaultValue) {
|
||||
super(); // Invoke superclass constructor
|
||||
this.defaultValue = defaultValue; // Remember the default value
|
||||
}
|
||||
|
||||
get(key) {
|
||||
if (this.has(key)) { // If the key is already in the map
|
||||
return super.get(key); // return its value from superclass.
|
||||
}
|
||||
else {
|
||||
return this.defaultValue; // Otherwise return the default value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This class computes and displays letter frequency histograms
|
||||
class Histogram {
|
||||
constructor() {
|
||||
this.letterCounts = new DefaultMap(0); // Map from letters to counts
|
||||
this.totalLetters = 0; // How many letters in all
|
||||
}
|
||||
|
||||
// This function updates the histogram with the letters of text.
|
||||
add(text) {
|
||||
// Remove whitespace from the text, and convert to upper case
|
||||
text = text.replace(/\s/g, "").toUpperCase();
|
||||
|
||||
// Now loop through the characters of the text
|
||||
for(let character of text) {
|
||||
let count = this.letterCounts.get(character); // Get old count
|
||||
this.letterCounts.set(character, count+1); // Increment it
|
||||
this.totalLetters++;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the histogram to a string that displays an ASCII graphic
|
||||
toString() {
|
||||
// Convert the Map to an array of [key,value] arrays
|
||||
let entries = [...this.letterCounts];
|
||||
|
||||
// Sort the array by count, then alphabetically
|
||||
entries.sort((a,b) => { // A function to define sort order.
|
||||
if (a[1] === b[1]) { // If the counts are the same
|
||||
return a[0] < b[0] ? -1 : 1; // sort alphabetically.
|
||||
} else { // If the counts differ
|
||||
return b[1] - a[1]; // sort by largest count.
|
||||
}
|
||||
});
|
||||
|
||||
// Convert the counts to percentages
|
||||
for(let entry of entries) {
|
||||
entry[1] = entry[1] / this.totalLetters*100;
|
||||
}
|
||||
|
||||
// Drop any entries less than 1%
|
||||
entries = entries.filter(entry => entry[1] >= 1);
|
||||
|
||||
// Now convert each entry to a line of text
|
||||
let lines = entries.map(
|
||||
([l,n]) => `${l}: ${"#".repeat(Math.round(n))} ${n.toFixed(2)}%`
|
||||
);
|
||||
// And return the concatenated lines, separated by newline characters.
|
||||
return lines.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// This async (Promise-returning) function creates a Histogram object,
|
||||
// asynchronously reads chunks of text from standard input, and adds those chunks to
|
||||
// the histogram. When it reaches the end of the stream, it returns this histogram
|
||||
async function histogramFromStdin() {
|
||||
process.stdin.setEncoding("utf-8"); // Read Unicode strings, not bytes
|
||||
let histogram = new Histogram();
|
||||
for await (let chunk of process.stdin) {
|
||||
histogram.add(chunk);
|
||||
}
|
||||
return histogram;
|
||||
}
|
||||
|
||||
// This one final line of code is the main body of the program.
|
||||
// It makes a Histogram object from standard input, then prints the histogram.
|
||||
histogramFromStdin().then(histogram => { console.log(histogram.toString()); });
|
|
@ -0,0 +1 @@
|
|||
console.log("Hello World!")
|
Loading…
Reference in New Issue