Finished Chap01

master
Jason Zhu 2020-12-17 01:50:38 +00:00
parent 05787f658e
commit 5ea4e5c80e
4 changed files with 304 additions and 1 deletions

View File

@ -17,7 +17,7 @@
], ],
// Use 'forwardPorts' to make a list of ports inside the container available locally. // 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. // Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install", // "postCreateCommand": "yarn install",

View File

@ -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`

View File

@ -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()); });

View File

@ -0,0 +1 @@
console.log("Hello World!")