Intro to Modern JavaScript with React
--- ## Brief history of JavaScript - Created in 10 days in 1995 - Shipped with NetScape Navigator, became scripting language of the web - Standardized in 1997 as ECMAScript ("European Computer Manufacturer's Association") - Called ECMAScript to avoid trademark issues - Browser implementations are generally called JavaScript - No new language standards from ECMAScript 3 in 1999 to 2009 - ECMAScript 4 edition was abandoned due to disputes - ECMAScript 5 released in 2009, 5.1 in 2011 - ECMAScript 6 released in 2015, called ES2015 - ECMAScript 7 released in 2016, called ES2016 - ECMAScript 8 released in June 2017, called ES2017 - ES.Next always refers to ongoing standardization efforts - Most of the features discussed today are part of ES2015 --- ## Browser support - Standards and browers are moving much more quickly now - Most consumer browsers are aggressively upgraded - For example, 25% of web users as of June 2017 are on Chrome 58, released in April 2017 - However, some users are on older browsers - We will discuss strategies to maintain compatibility with older browsers --- #### var/globals to const/let Standard: ES2015 - var is execution-scoped (all vars are accessible from the top-level of a function) - all global vars are part of an object ("window" in a browser environment) ```javascript var myGlobal = true; console.log(window.myGlobal); // true function myFunction() { for(var i = 0; i !== 5; i++) { if(i === 3) { var text = "Hello, world"; } } console.log(i, text); // 5, "Hello world" } myFunction(); ``` ??? notes --- #### var/globals to const/let 2 - let is block scoped ```javascript let test = true; console.log(window.test); // undefined for(let i = 0; i !== 5; i++) { if(i === 3) { let text = "Hello, world"; } } // ReferenceError: i is not available outside of for loop console.log(i); // ReferenceError: text is not available outside of if statement console.log(text); ``` --- #### var/globals to const/let 3 - const follows the same rules as let, but is immutable (cannot be re-assigned) ```javascript const myVariable = true; // TypeError: Assignment to constant variable myVariable = false; ``` --- #### Classes Standard: ES2015 ```javascript class Animal { constructor(species, sound) { this.species = species; this.sound = sound; } speak() { console.log(this.species, 'says', this.sound); } } const dog = new Animal("dog", "woof!"); dog.speak(); // dog says woof ``` --- #### Classes 2: inheritance ```javascript class Dog extends Animal { constructor(name, breed) { super("dog", "woof!"); this.name = name; this.breed = breed; } } const dog = new Dog('Spot', 'Dalmatian'); ``` --- #### Classes 3: Static methods ```javascript class Account { constructor(assets, debt) { this.assets = assets; this.debt = debt; } static makeEmptyAccount() { return new Account(0, 0); } } Account.makeEmptyAccount(); ``` --- #### Arrow functions Shorter than writing functions ```javascript function add(a, b) { return a + b; } ``` ```javascript // Equivalent to the above function const add = (a, b) => a + b; // You can use braces + return as well if you need to do something more complex const add = (a, b) => { return a + b; } // No parentheses needed for single-argument functions const add2 = a => a + 2 ``` --- #### Arrow functions 2 Arrow functions inherit `this` and `arguments` from the context they are written in. ```javascript this.message = "Hello world"; var object = this; setInterval(function() { // To reference this.message, we have to save off 'this' as a separate variable // Because this will have changed inside of this callback function console.log(object.message); }, 1000) ``` ```javascript this.message = "message"; setInterval(() => { // No additional code required to reference 'this' console.log(this.message); }, 1000); ``` Very handy when working with deeply-nested callbacks --- #### Template literals 1 lots of javascript code uses string concatenation ```javascript let person = { name: "James", age: 24 }; console.log("Name: '" + person.name + "', age: " + person.age); // Name: 'James', age: 24 ``` --- #### Template literals 2 Uses backticks ```javascript let person = { name: "James", age: 24 } console.log(`Name: '${person.name}', age: ${person.age}`); // Name: 'James', age: 24 ``` --- #### Destructuring bind ``` javascript var color = [255, 0, 0]; var red = color[0]; var green = color[1]; var blue = color[2]; ``` #### becomes ```javascript const color = [255, 0, 0]; const [red, green, blue] = color; ``` --- #### Destructuring bind 2 also works on objects ```javascript var person = { name: "James", age: 24, occupation: "Electrician" } var name = person.name; var age = person.age; var occupation = person.occupation; ``` #### becomes ```javascript const person = { name: "James", age: 24, occupation: "Electrician" }; const {name, age, occupation} = person; ``` --- #### Destructuring bind 3 Can be nested arbitrarily ```javascript const person = { name: "James", age: 24, occupations: ["Electrician", "Plumber"] }; const {name, age, occupations: [occupation1, occupation2]} = person; console.log(name, age, occupation1, occupation2); // James 24 Electrician Plumber ``` --- #### Destructuring bind 4 Can even be used in function parameters ```javascript function printPerson({name, age}) { console.log(name, age); } var person = { name: "James", age: 24 }; printPerson(person); // James 24 ``` --- #### Promises 1 Doing things asynchronously in JavaScript often results in "callback hell" ```javascript step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { // Do something with value3 }); }); }); ``` --- #### Promises 2 Standard: ES2015 ```javascript step1() // returns a Promise .then(value1 => step2(value1)) .then(value2 => step3(value2)) .done(value3 => { // Do something with value3 }).catch(() => { // Catch errors at any point during this. }); ``` --- #### Async/await Standard: ES2017 ```javascript async function myFunction() { const value1 = await step1(); const value2 = await step2(value1); const value3 = await step3(value2); return value3; // returns a promise } ``` --- ##### Modules #### globals ```html ``` --- #### commonjs ```javascript var $ = require("jquery"); var bootstrap = require("bootstrap"); module.exports = { myFunction: function() {}, myVariable: true, // .... } ``` --- #### es2015 modules ```javascript import $ from 'jquery'; import bootstrap from 'bootstrap'; export function myFunction() { } export const myVariable = true; ``` --- #### es2015 modules 2 ES2015 modules are static, and imports cannot be changed at runtime. ```javascript import $ from 'jquery'; $ = somethingElse; // error! ``` This allows an intelligent bundler to eliminate dead code. ("tree-shaking") --- #### window.fetch XMLHTTPRequest, pretty verbose ```javascript var req = new XMLHttpRequest(); req.addEventListener("load", onLoad); req.open('GET', 'https://example.com/example.json'); req.send(); ``` Or jQuery ```javascript $.get('https://example.com/example.json', function(response) { }); ``` --- #### window.fetch 2 Built into browser, based on Promises ```javascript window.fetch('https://example.com/example.json') .then(response => response.json()) .then(result => { // do something with result }); ``` Or in an async function ```javascript async function() { const response = await window.fetch('https://example.com/example.json'); const result = await response.json(); // result is available from here } ``` --- #### JSX - mix HTML or other XML-like formats with JavaScript code - not a proposed part of any standard - used by react, react native, and other web frameworks ```javascript const element =
Hello world
``` equivalent to *normal JavaScript function calls* ```javascript const element = React.createElement('p', null, 'Hello world'); ``` --- #### Problem Browser support is highly variable --- #### Solution: transpilation - Transpilation = transforming source code to source code - Support new language features by compiling new features to old-style JavaScript - However, transpilation generally doesn't handle runtime functionality such as window.fetch or Promises. #### Solution: polyfills - A polyfill is basically a small bit of code that checks whether or not a feature is supported - If not, will extend the browser environment with that functionality --- #### Babel - transpiler from Facebook - very extensible, supports multiple standards as well as plugins to add new features such as JSX ```javascript const name = "James"; const age = 24; const person = {name, age}; console.log(`Name: ${person.name}, age: ${person.age}`); ``` compiles down to ```javascript var name = "James"; var age = 24; var person = { name: name, age: age }; console.log("Name: " + person.name + ", age: " + person.age); ``` --- #### Webpack - Handles running various preprocessors, bundling and compressing resulting code and static resources - Not required for compatibility, but useful to handle a complex build process - In combination with ES2015 modules, can remove unused code --- #### React React is a library for building interactive user interfaces in a declarative style. In combination with the new language features, it is a very nice way to build interactive web applications with code that is easy to reason about. ??? stop here for livecoding --- #### JSX ```javascript ReactDOM.render(
Hello world
, document.body); ``` React applications work by building up a Virtual DOM with JSX syntax and components. Recall that JSX results in normal objects, which can be stored in variables & arrays, and returned as the result of functions ```javascript const paragraph =
Hello world
; // perfectly valid code ``` ```javascript const paragraph = React.createElement('p', null, 'Hello world'); // equivalent to the above ``` ??? slides for if livecoding doesn't work for some reason --- #### Components Most React applications are composed of components ```javascript class App extends React.Component { render() { return
Hello world
} } ``` Components can be mixed in with normal HTML in JSX syntax ```javascript ReactDOM.render(
, document.body); // will result in an instance of App being created & rendered ``` --- #### Virtual Document Object Model ReactDOM.render takes the tree of components and HTML elements that results from this and creates actual instances of the components, only updating the page when absolutely necessary. This is called the virtual document object model (virtual DOM or VDOM for short). The primary advantage of this is that the programmer does not have to think about updating the actual page, only about the state of his application. --- #### VDOM 2 There are other advantages to this abstraction For example, there is ReactDOMServer which allows pages to be rendered on the server-side; this can massively speed up applications by not requiring clients to render pages. --- #### VDOM 3 Many libraries use a similar concept, although it may not be implemented in exactly the same way. --- #### State Some components have state. ```javascript class Counter extends React.Component { constructor() { // Initialize state this.state = { message: "Hello world" }; } render() { return
{this.state.message}
} } ``` If this.state is changed using the setState method at any point, the app will be re-rendered automatically --- #### State 2 Other components without state can be written as simple functions ```javascript const Message = (props) =>
Message: {props.text}
ReactDOM.render(
, document.body); ``` --- #### Types of components React applications are a mix of components which do more complex things like - handle user actions - dispatch asynchronous requests - have internal state And simpler components which handle display These can be thought of as *container* and *presentational* components Even more optimizations are available when we know a component is not going to need things like internal state --- #### A simple counter application ```javascript class Counter extends React.Component { constructor() { this.state = { count: 0 }; } increment() { this.setState({ count: this.state.count + 1 }); } render() { return
Clicked {this.state.count} times
this.increment()}>Click me
} } ``` --- ## Thanks for putting up with me. # [upvalue.io/talks](upvalue.io/talks) Slides and code available from here. ---