The State of JavaScript (2015)
-
Upload
domenic-denicola -
Category
Technology
-
view
20.247 -
download
3
Transcript of The State of JavaScript (2015)
the state of javascript
hi, i’m domenic Google Chrome TC39 WHATWG HTML and Streams Standards Promises jsdom
let’s talk about
> where we’ve come from> javascript today> new platform innovations> where we’re going
where we’vecome from
history
1995: form validation, image rollovers
1997: ECMA-262 edition 1, Internet Explorer 4, DHTML
1999: ES3 (function expressions, try/catch/finally, regexps, …)
2005: Ajax
2006: jQuery
2008: V8 (the speed race begins), JS: The Good Parts
2009: ES5, Node.js, PhoneGap, JSConf, ServerJS/CommonJS
2010: Backbone.js, RequireJS
2012: Windows 8, Nodecopter
2013: Nodebots, next-gen MVC, Extensible Web, asm.js
2015: io.js, ES2015, MS Edge, Node.js 4, web assembly
javascripttoday
es2015 is here
es2015: syntaxClass sugar: class, extends, super
Arrow functions: arr.map(x => x * x)
Destructuring: var { x, y } = getPoint()
Rest/spread: var [first, …rest] = els; Math.max(...myArray)
Parameter defaults: function parseInt(x, base = 10) { }
Block scoping: { let x = 5; const y = 10; }
es2015: data structures
Map: object-to-object O(1) access time
Set: O(1) lookup and storage
WeakMap/WeakSet: private state and branding
Iteration protocol: for-of across anything, even user iterables
es2015: game-changersGenerators: lazy sequences and async/await-like syntax
Promises: standardized async; play well with generators
Proxies: virtual objects, no more .get(…)/.set(…, …)!
Template strings: jsx`<a href="${url}">${text}</a>`
Subclassable built-ins: class Elements extends Array { … }
es2015 in the wild
new code styles
{ "no-var": 2, "object-shorthand": 2, "prefer-arrow-callback": 2, "prefer-const": 2, "prefer-template": 2}
https://github.com/tmpvar/jsdom/blob/master/lib/jsdom/living/document-type.js
"use strict";const NODE_TYPE = require("../living/node-type");
const privates = Symbol("DocumentType internal slots");
module.exports = core => { core.DocumentType = class DocumentType extends core.Node { constructor(secret, ownerDocument, name, publicId, systemId) { if (secret !== privates) { throw new TypeError("Invalid constructor"); }
super(ownerDocument); this[privates] = { name, publicId, systemId }; }
get name() { return this[privates].name; } ⋮
promises everywhere
generators for async
https://github.com/domenic/wattsi-server/blob/master/lib/app.js
const outDirectory = randomDirectoryName();yield mkdirp(outDirectory);
try { try { const result = yield execFile(config.wattsiPath, [sourceFilePath, outDirectory, caniuseFilePath, w3cbugsFilePath]);
const outputFile = path.join(outDirectory, "output.txt"); yield fs.writeFile(outputFile, `${result.stdout}${result.stderr}`, { encoding: "utf-8" }); } catch (e) { if (e.stdout) e.message = `${e.stdout}${e.stderr}`; this.throw(e, 400); }
const zipFilePath = `${outDirectory}.zip`; yield execFile("7za", ["a", "-tzip", "-r", zipFilePath, `./${outDirectory}/*`]);
this.type = "application/zip"; this.body = fs.createReadStream(zipFilePath);} finally { yield rimraf(outDirectory);}
transpile for browsersand nonstandard features
https://github.com/unicorn-standard/react-callback-register
@callbackRegisterclass MyComponent extends React.Component { static propTypes = { onClick: React.PropTypes.func }
@callbackRegister.on('click') descriptiveName() { // Do your stuff }
render() { return <div {...this.callbacks} /> }}
new platforminnovations
class CustomImage extends HTMLElement { constructor(src) { super(); if (src !== undefined) this.src = src; }
get src() { return (new URL(this.getAttribute("src"), this.baseURI)).href; } set src(value) { this.setAttribute("src", value); }
[Element.attributeChanged](name) { if (name === "src") updateShadowDOM(this, this.src); }}
document.registerElement("custom-image", CustomImage);https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Constructor-Dmitry.md
custom elements
https://www.npmjs.com/search?q=service+worker
toolbox.precache(['/index.html', '/site.css', '/images/logo.png']);
toolbox.cache('/data/2014/posts.json');toolbox.uncache('/data/2013/posts.json');
toolbox.router.get('/:foo/index.html', (req, values) => { return new Response( `Handled a request for ${req.url} with :foo as ${values.foo}`);});
toolbox.router.get('/myapp/a', toolbox.networkFirst);toolbox.router.get('/myapp/b', toolbox.networkOnly);toolbox.router.get('/myapp/c', toolbox.cacheFirst);toolbox.router.get('/myapp/:page', toolbox.cacheOnly);toolbox.router.get('/(.*)', toolbox.fastest);
https://github.com/GoogleChrome/sw-toolbox
service workers
registerPaint('circle', class { static get inputProperties() { return ['--circle-color']; }
paint(ctx, geom, properties) { // Change the fill color. ctx.fillStyle = properties.get('--circle-color');
// Determine the center point and radius. const x = geom.width / 2; const y = geom.height / 2; const radius = Math.min(x, y);
// Draw the circle \o/ ctx.beginPath(); ctx.arc(x, y, radius, 0, 2 * Math.PI, false); ctx.fill(); }});
#myElement { --circle-color: red; background-image: paint(circle);}
https://drafts.css-houdini.org/css-paint-api/#example-1
custom paint
where we’regoing
https://tc39.github.io/ecma262/
spec version numbers are bullshites6, es2015, es2016… who cares?
you should not.
coming soon
async function getUserImages() { const response = await fetch("http://example.com/users"); const users = await response.json();
return Promise.all(users.map(async (u) => { return { name: u.name, image: (await fetch(u.imageUrl)).body }; }));}
async/await
for (let i = 0; i < maxIterations; ++i) { const zRe24 = SIMD.Float32x4.mul(zRe4, zRe4); const zIm24 = SIMD.Float32x4.mul(zIm4, zIm4);
const mi4 = SIMD.Float32x4.lessThanOrEqual(SIMD.Float32x4.add(zRe24, zIm24), four4);
if (mi4.signMask === 0x00) { break; }
const newRe4 = SIMD.Float32x4.sub(zRe24, zIm24); const newIm4 = SIMD.Float32x4.mul(SIMD.Float32x4.mul(two4, zRe4), zIm4); zRe4 = SIMD.Float32x4.add(cRe4, newRe4); zIm4 = SIMD.Float32x4.add(cIm4, newIm4); count4 = SIMD.Int32x4.add(count4, SIMD.Int32x4.and(mi4, on4));}
SIMD.js
https://github.com/PeterJensen/mandelbrot/blob/master/js/mandelbrot.js
watch out for
// 64 bit integersconst fifteen = 5UL + 10UL;
// Memory-efficient structurally-equal "structs"const Point = new ValueType({ x: float64, y: float64 });const point = new Point({ x: 1.5, y: 2.4 });assert(point === new Point({ x: 1.5, y: 2.4 }));
// Custom literals and operator overloadsconst romaineLettuce = 0x3B5323FFrgba;const length = 50percent + 10em + 5px;el.css.width += 2rem;
value types
https://github.com/nikomatsakis/typed-objects-explainer/
class BusinessLogic { @performance doImportantComputation() { // ... }}
(new BusinessLogic()).doImportantComputation();// => doImportantComputation: 102ms
decorators
https://www.npmjs.com/package/decorator-performance
startSpinner();
const p = fetch(url) .then(r => r.json()) .then(data => fetch(data.otherUrl)) .then(res => res.text()) .then(text => updateUI(text)) .catch(err => showUIError(err)) .finally(stopSpinner);
cancelButton.onclick = () => p.cancel();
cancelable promises
async function* directoryEntries(path) { const dir = await opendir(path);
try { let entry; async for (const entry of readdir(dir)) { yield path.resolve(entry); } } finally { await closedir(dir); }}
async iterators
<script type="module">
import a from "./a.js";import { b } from "../b.js";import $ from "https://cdn.example.com/jquery.js";
</script>
module loading
one last thing…
web assembly!?!?https://github.com/WebAssembly/design