项目作者: livionaef

项目描述 :
Javascript Toolbox:
高级语言: HTML
项目地址: git://github.com/livionaef/JS-Toolbox.git
创建时间: 2020-05-25T08:45:32Z
项目社区:https://github.com/livionaef/JS-Toolbox

开源协议:

下载


JS-Toolbox

1. Intro & Functions

“You only understand what you can build by yourself => use no dependencies”

Canvas

  1. const canvas = document.getElementById("canvas");
  2. const context = canvas.getContext("2d");
  3. context.fillStyle = "black";
  4. context.fillRect(0, 0, canvas.width, canvas.height);

Key events

  1. const rightArrow = 39;
  2. const leftArrow = 37;
  3. window.onkeydown = evt => {
  4. (evt.keyCode === rightArrow) ? : ;
  5. };

Game loop

  1. setInterval( () => {
  2. nextBoard();
  3. display(context);
  4. }, 1000 / 5);

Fundamentals of Lambda Calculus & Functional Programming in JavaScript - YouTube Video

Video-Link

Example

A function plus that returns the sum of its arguments:

  1. const plus = x => y => x + y;

2. Lambda

JavaScript Variables

Only use let and const:

  1. let x = ...; // mutable, local scope
  2. const x = ...; // immutable, local scope

IIFE

immediately invoked function expression

  1. function foo() {..}; foo()
  2. ( function foo() {..} ) ()
  3. ( function() {..} ) ()
  4. ( () => {..} ) ()

Alpha Translation

  1. const id = x => x
  2. const id = y => y

Beta Reduktion

  1. ( f => x => f(x) ) (id) (1)
  2. ( x => id(x)) (1)
  3. ( id(1))
  4. (x => x) (1)
  5. 1

Eta Reduktion

  1. x => y => plus (x) (y)
  2. x => plus (x)
  3. plus

Examples

F3 is a proper eta reduction of F2

  1. const id = x => x;
  2. const konst = x => y => x;
  3. const F1 = x => y => konst (id) (x) (y);
  4. const F2 = x => konst (id) (x);
  5. const F3 = konst (id);

a1 is a proper beta expansion of a2

  1. const id = x => x;
  2. const a1 = y => id(y);
  3. const a2 = y => y;

a2 is a proper beta reduction of a1

  1. const id = x => x;
  2. const a1 = y => id(y);
  3. const a2 = y => y;

id1 and id2 are alpha-equivalent

  1. const id1 = x => x;
  2. const id2 = y => y;

3. Algebraic Data Types

“I recommend that you write programs as though JavaScript had been designed correctly.”

  • Douglas Crockford, How JavaScript works, p. 6.2

Atomic Lamda Terms

  1. // atoms
  2. const id = x => x;
  3. const konst = x => y => x;
  4. // derived true, false, and, or, equals, …
  5. const F = …;
  6. const T = …;

Pair, Product Type

  1. const pair = x => y => f => f(x)(y);
  2. const fst = p => p(T);
  3. const snd = p => p(F);

Pair encoding

  1. const person =
  2. firstname =>
  3. lastname =>
  4. age =>
  5. pair (pair(firstname)(lastname)) (age);
  6. const firstn = p => fst(fst(p));
  7. const lastn = p => snd(fst(p));
  8. const age = p => snd(p);

Either, Co-Product, Sum

  1. // dual of the product
  2. const pair = x => y => f => f(x)(y); // one ctor
  3. const fst = p => p(T); // accessor 1
  4. const snd = p => p(F); // accessor 2
  5. // here we have now the basic sum type
  6. const Left = x => f => g => f(x); // ctor 1
  7. const Right = x => f => g => g(x); // ctor 2
  8. const either = e => f => g => e(f)(g); // accessor

Special Case: Maybe

  1. // go around null / undefined
  2. const Nothing = Left ();
  3. const Just = Right;
  4. const maybe = either;
  5. maybe (expressionThatMightGoWrong)
  6. (handleBad)
  7. (handleGood);

Example

  1. // error handling with either
  2. const eShow = result => result (msg => msg) (val => "Result is:" + val);

4. Map, Filter, Reduce

“Developers seem to love those languages most, in which they understood the value of higher-order functions.”

Map

  1. const times = a => b => a * b;
  2. const twoTimes = times(2);
  3. [1, 2, 3].map(x => times(2)(x));
  4. [1, 2, 3].map(times(2));
  5. [1, 2, 3].map(twoTimes);

Filter

  1. const odd = x => x % 2 === 1;
  2. [1, 2, 3].filter(x => x % 2 === 1);
  3. [1, 2, 3].filter(x => odd(x));
  4. [1, 2, 3].filter(odd);

Reduce

  1. const plus = (accu, cur) => accu + cur;
  2. [1, 2, 3].reduce((accu, cur) => accu + cur);
  3. [1, 2, 3].reduce(plus);
  4. // variant with initial accu value as 2nd argument
  5. // then cur starts at first element
  6. [1, 2, 3].reduce(plus, 0);

Examples

  1. // function that checks which numbers in an array are divideable
  2. // by the given argument
  3. const divides = x => y => y % x === 0;
  1. // function that joins values of an array together with given argument
  2. const join = (a) => (b, c) => b + a + c;

5. Scripting, PWA, Plotter, Excel

“Unfortunately, JS has a misfeature called Automated Semicolon Insertion. It can fail in bad ways, so write like a professional.”

  • Douglas Crockford, “How JavaScript works.”

Why Scripting?

  • Command Line
  • Automation
  • Build System
  • Templating
  • Code Distribution
  • Formulae
  • Business Rules
  • Smart Configuration
  • Product Lines
  • DSL
  • Self Modifying Code

Progressive Web App

  1. document.write('<script src=...');

Function Plotter: eval

Works as if the code was copied verbatim in the place of the eval. => You share the scope.

  1. eval('some code');

Function Plotter: Function()

Function() is like eval() but declares parameters and executes in the global scope. It creates a reference.

  1. const add = Function('x', 'y', 'return x+y');
  2. add(1, 2);
  3. add(2, 3); // no need to re-parse

Scripting Caution

In JavaScript you cannot exclude possibly harmful side effects from scripts that are loaded from foreign sources…

=> Privacy, Security, Stability

Examples

Calculate the bonus with given attributes:

  1. const bonusCalculation = x => x.bonus = eval(x.revenue) * factor_;

Calculate the bonus with given attributes using Function():

  1. const bonusCalculation = Function('x', 'return x.bonus = x.revenue *' + factor_);

6. Objects

“It’s called object-oriented to tell you what you should do with it: object!”

  • Phil Wadler, quoted from memory

Open & dynamic

JS “Objects”.

  1. const good = {
  2. firstname : "Good",
  3. lastname : "Boy",
  4. getName : function() {
  5. return this.firstname + " " + this.lastname
  6. }
  7. };
  8. // no safety but super dynamic
  9. // unobvious how to share structure
  10. // beware of "this"! See Adam Breindl last week.

Closed & explicit

Closure scope, no “this”.

  1. function Person(first, last) {
  2. let firstname = first; // optional
  3. let lastname = last;
  4. return {
  5. getName: function() {
  6. return firstname + " " + lastname }
  7. }
  8. }
  9. }
  10. // best safety, easy to share structure, but no class

Mixed & classified

Depends on “new”. Is the “default” construction.

Still dynamic but all “instances” can be changed at once by changing the prototype!

  1. const Person = ( () => { // lexical scope
  2. function Person(first, last) { // ctor, binding
  3. this.firstname = first;
  4. this.lastname = last;
  5. }
  6. Person.prototype.getName = function() {
  7. return this.firstname + " " + this.lastname;
  8. };
  9. return Person;
  10. }) (); // IIFE
  11. // new Person("Good", "Boy") instanceof Person

Example

Check wether two Arrays are equal:

  1. Array.prototype.eq = function(array) {
  2. if (this.length !== array.length) return false;
  3. for (let i = 0; i < array.length; i++) {
  4. if (this[i] !== array[i]) return false;
  5. }
  6. return true;
  7. }

7. Classes

“Classes tend to be bad modules.”

  • D. Crockford, How JS works, p. 17.0

class Keyword

  1. class Person {
  2. constructor(first, last) {
  3. this.firstname = first;
  4. this.lastname = last
  5. }
  6. getName() {
  7. return this.firstname + " " + this.lastname
  8. }
  9. }
  10. // new Person("Good", "Boy") instanceof Person

extends Keyword

  1. class Student extends Person {
  2. constructor (first, last, grade) {
  3. super(first, last); // never forget
  4. this.grade = grade;
  5. }
  6. }
  7. const s = new Student("Top","Student", 5.5);

Prototype chain

  1. const s = new Student()
  2. // s.__proto__ === Student.prototype;
  3. // Object.getPrototypeOf(s) === Student.prototype;
  4. // => s instanceof Student

Example

Function composition -> it must work for all functions!

  1. Function.prototype.then = function(bracketFunc) {
  2. // this(number -> result of the first function
  3. // with the value at the end f.e. ..(1))
  4. const compose = bracketFunc => number => bracketFunc( this(number) );
  5. return compose(bracketFunc);
  6. }

8. Moves, User Interfaces

“Live’s a dance you learn as you go. Sometimes you lead, sometimes you follow.”

  • John Michael Montgomery

Compare with Dancing

  1. You must learn the moves.
  2. Then you can combine the moves and adapt to the situation at hand.

Recognize Moves

  • Become aware what you do.
  • We program collaboratively and look for moves.

Task 1: Improve the Tests

  • More structure.
  • Better reports when tests fail.
  • smooth transition.

Task 2: Todo List Example

  • What is the expected result?
  • What is the simplest thing that could possibly work?

Moves - Your Choice

0: Explore

  • Technical feasibility, hypotheses, border cases.
  • The goal is to learn and verify, delete when finished.
  • Give yourself a timebox.

1: Start at the End

  • Make static “sketch” of the result before adding dynamic features.
  • Dynamic sketches: all JS, CSS in a single HTML file.

2: Extract

  • Replace static values with variables.
  • Replace repetitions with mappings and loops.

3: Abstract

  • Discover the concept behind what you have extracted. Give it a name.
  • It should work for itself and in combination.
  • Revert if you cannot find one.

4: Reorganize

  • Organize and re-factor to make your future work easier.
  • Facilitate extensions or improvements.
  • Prepare for release.

5: Release

  • The solution must stand on its own without tacit knowledge or external help.
  • Tests, documentation, examples.
  • Before every push to the Repository.

6: Retrospective

  • What to keep?
  • What to try differently next time?

Observations

  • Balance & distance
  • Which technologies support my moves: dynamic exploration, refactoring
  • Per feature, per project, whole career, …

Example

Failsafe callback:

  1. const failSafe = defaultValue => callback => argToCallback => {
  2. return argToCallback === null ? defaultValue : callback(argToCallback);
  3. }

9. UI Engineering, MVC

“Frameworks and APIs change fast. Software design principles are evergreen. Learn principles that translate across language barriers.”

  • Eric Elliot

Callback - HOF

Higher-order Function.

  1. function test(name, callback) {
  2. const assert = Assert(); // prework
  3. callback(assert); // callback
  4. report(name, assert.getOk()); // postwork
  5. }

Observable

  1. const Observable = value => {
  2. const listeners = []; // many
  3. return {
  4. onChange: callback => listeners.push(callback),
  5. getValue: () => value,
  6. setValue: val => {
  7. if (value === val) return; // protection
  8. // ordering
  9. value = val;
  10. listeners.forEach(notify => notify(val));
  11. }
  12. }
  13. };

MVC

MVC Bild

Example

Using Observable that it keeps track of the sum of all values:

  1. trackable.onChange( _ => sum += trackable.getValue() );

10. Async Programming

“Don’t call us. We call you.”

  • Hollywood

Testing

  1. test("todo-memory-leak", assert => {
  2. const todoController = TodoController();
  3. todoController.onTodoAdd(todo => {
  4. todoController.onTodoRemove( (todo, removeMe) => {
  5. removeMe(); // idea: self remove
  6. });
  7. });
  8. for (let i=0; i<10000; i++){
  9. const todo = todoController.addTodo();
  10. todoController.removeTodo(todo);
  11. }
  12. });

Callback, Events

  1. function start() {
  2. //...
  3. window.onkeydown = evt => {
  4. // doSomething();
  5. };
  6. setInterval(() => {
  7. // doSomething();
  8. }, 1000 / 5);
  9. }

Promise

Most prominent use:

  1. fetch ('http://fhnw.ch/json/students/list')
  2. .then(response => response.json())
  3. .then(students => console.log(students.length))
  4. .catch (err => console.log(err)

Success / Failure callbacks:

  1. // definition
  2. const processEven = i => new Promise( (resolve, reject) => {
  3. if (i % 2 === 0) {
  4. resolve(i);
  5. } else {
  6. reject(i);
  7. }
  8. });
  9. // use
  10. processEven(4)
  11. .then ( it => {console.log(it); return it} ) // auto promotion
  12. .then ( it => processEven(it+1))
  13. .catch( err => console.log( "Error: " + err))

Async / Await

  1. const foo = async i => {
  2. const x = await processEven(i).catch( err => err);
  3. console.log("foo: " + x);
  4. };
  5. foo(4);

Other variant:

  1. async function foo(i) {
  2. try {
  3. const x = await processEven(i);
  4. console.log("foo: " + x);
  5. }
  6. catch(err) { console.log(err); }
  7. };
  8. foo(4);

Example

A NullSafe construction in the style of a Promise:

  1. const NullSafe = x => {
  2. const isNullSafe = y => y && y.then;
  3. const maywrap = y => isNullSafe(y) ? y : NullSafe(y);
  4. return {
  5. then: fn => (x !== null && x != undefined)
  6. ? maywrap(fn(x))
  7. : NullSafe(x)
  8. }
  9. };

11. Data Flow

Coordination schemata

Similar to concurrency

  1. No coordination needed
  2. Sequence (of side effects)
  3. Dependeny on former results

No Coordination

Nothing to do !

  • Execution model: confined
  • All actions run independently

Sequence

Actor

  • In a sequence of actions, each action can only start if the preceding one has finished
  • How to achieve this => Delegated Coordination => Scheduler

Result Dependency

  • Action B and C need the result of action A
  • A must be executed exactly once before B and C
  • How to do this => Implicit Coordination => DataFlowVariable

Scheduler Idea

  • Queue (FIFO) of functions that are started with a lock
  • Callback unlocks

DataFlowVariable

  • Function, that sets a value if it is not already set. Returns the value.
  • Lazy: Access to variables that will become available later
  • Trick: Do not set the value, but a function that returns the value

12. Modules

“Well-structured software is easy to write and to debug, and provides a collection of modules that can be reused to reduce future programming costs.”

  • John Hughes

Why Modules?

  • Organize the Code
  • Clear dependencies
  • Avoid errors: Globals, Scoping, Namespace
  1. // avoid something like this in your html document
  2. <script src="fileA.js">
  3. <script src="fileB.js">
  4. <script src="fileC.js">
  5. // if fileA.js has a reference on fileC.js it won't work !!!

Distinguish

  • How I want to edit the code
  • How I want to deliver the code

ES6 Modules

They are not…

  • Packages (those have versions)
  • Dependencies, Libraries, Releases
  • Units of publication
  • Objects

Package Manager

webpack, npm, bower, yarn, …

Build Tools

webpack, npm, grunt, gulp, …

Legacy module systems

CommonJS, AMD, UMD, …

Legacy Module Loader / Bundler

RequireJS, SystemJS, browserify, …

Modules are async

  1. // Use URI format as follows: "./myFile.js"
  2. <script src="./myFile.js" type="module"> // type implies "defer"
  3. import ("./myFile.js").then( modules => ... )
  4. // invasive, transitive impact

Import Variants

Always explicit!

  1. // most used
  2. import "module-name";
  3. import { export1, export2 } from "module-name";
  4. // other variants
  5. import defaultExport from "module-name";
  6. import * as name from "module-name";
  7. import { export } from "module-name";
  8. import { export as alias } from "module-name";
  9. var promise = import("module-name");

Export Variants

Always explicit!

  1. // most used
  2. export { name1, name2, ... , nameN };
  3. // other variants
  4. export function FunctionName() { .. }
  5. export const name1, name2, ... , nameN; // or let
  6. export class ClassName { .. }
  7. export default expression;
  8. export { name1 as default, .. };
  9. export * from .. ;
  10. export { name1, name2, ... , nameN } from .. ;

Impacts

  • implicit “use-strict” exports are read-only !
  • no Global object, no Global “this”, no Global hoisting
  • implicit “defer” mode => document.writeln is no longer useful
  • Modules are Namespaces
  • Modules are Singletons

SOP - Single Origin Policy

  • Modules are subject to the SOP
  • Problem at construction time: the File System is a null origin

Useful Tools

  • Developer Mode (suppress SOP) -> don’t forget to set back!
  • Local Webserver
  • Disable cache!
  • Bundler (Rollup, Parcel, Webpack, …)
  • Start Browser in Debug mode

Resources

13. Transpilers: TypeScript, PureScript, Elm

“The limits of my language are the limits of my world.”

  • Ludwig Wittgenstein, Tractatus Logico-Philosophicus

What they have in common

  • All are transpiling to JavaScript !
  • Allow React / Elm Architecture for functional JavaScript / SPA
    • TypeScript + React
    • PureScript + Pux / Halogen
    • Elm

The Cycle

  1. View -> Action -> State -> State ___________|
  2. ^ |
  3. |__________________________________________|

TypeScript

  • Typed state
  • Actions as functions / lamdas
  • State immutability with discipline
  • Object / component abstraction

Elm

  • Typed state
  • Action type with values
  • State is immutable
  • Update function is a fold
  • Function composition

PureScript / Pux

  1. // signature
  2. // name quantifier type variables
  3. konst :: forall a b . a -> b -> a
  4. // definition
  5. konst x y = x

Calling JavaScript (FFI)

TypeScript Type declaration
PureScript Type declaration
Elm Port / Flag

Applicability

TypeScript JS Environment
PureScript JS Environment
Elm Browser

Paradigm

TypeScript OO with Generics
PureScript Functional
Elm Functional

Approach

TypeScript Language
PureScript Language & Tools
Elm Programming System

Cool

TypeScript Sum (union) type , String Literal type
PureScript Eff Monad, [GADT]
Elm Time travel debug , SemVer guarantee

More Transpilers

ClojureScript Clojure (Lisp)
GHCJS Haskell
Babel JS
CoffeeScript JS++
GrooScript Groovy

14. Crazy JavaScript