Posts

Showing posts from October, 2015

Reader survey 2015

Dear readers! If you would, please fill out my reader survey . It won’t take long and will help improve this blog. I will publish a summary of the results, once the survey is closed. Last day of survey: Monday, November 9, 2015 Thank you! Axel

The traversal order of object properties in ES6

The ECMAScript 6 specification defines in which order the properties of an object should be traversed. This blog post explains the details. Why specify the traversal order? Traditionally, a JavaScript object is basically a map from strings to arbitrary values. The inherent nature of such a data structure is for entries to be unordered, which explains why, for a long time, the order in which properties are traversed was left unspecified in JavaScript (to be handled by engines as they saw fit). However, most engines ended up having the same order and now code depends on it. Therefore, using a different order breaks web apps, which is why requiring an order makes sense. In general, there are two possible approaches for preventing code from breaking in the manner that I’ve just described: Specify an order that code can depend on. Specify that engines must make it impossible for code to rely on an order, by choosing a different order each time. The latter is hard, which is why the former ap...

Influences on ECMAScript 6

This is a list of a few ECMAScript 6 features and what their influences were: Iteration : Python (but with a modified protocol) Generators : Python Arrow functions : CoffeeScript const : The name comes from C++ (the latest C standard borrowed it from C++), but it behaves more like Java’s final . let : is old, became popular via BASIC. Also frequently appears in functional programming languages (Lisp, ML, etc.), but creates immutable bindings there. Template literals : E ( quasi literals ) Destructuring : Lisp (destructuring bind) Modules : CommonJS, AMD Species pattern ( Symbol.species ): Smalltalk Promises :, also often called futures , are an old construct from concurrent programming languages. But ES6 Promises don’t block, they accept continuations via callbacks.

ECMAScript proposal: function-callable classes

This blog post describes the proposed ECMAScript feature “ call constructor ” ( stage 1 ). Classes can’t be function-called in ES6 In ECMAScript 6, classes can’t be function-called: class Point { constructor(x, y) { this.x = x; this.y = y; } } let p1 = new Point(1, 2); // OK let p2 = Point(3, 4); // TypeError For ES6, there was no categorical objection to classes being function-called. The error was only thrown so that handling function calls via classes could be added later. Function-callable constructors in ES6 If you want to implement a constructor Point that can be both function-called and constructor-called, you have no choice but to use a constructor function in ES6: function Point(x, y) { if (!new.target) { // Point was function-called return new Point(x, y); } this.x = x; this.y = y; } let p1 = new Point(1, 2); // OK let p2 = Point(3, 4); // OK Functi...

Why is there a “temporal dead zone” in ES6?

In ECMAScript 6, accessing a let or const variable before its declaration (within its scope) causes a ReferenceError . The time span when that happens, between the creation of a variable’s binding and its declaration, is called the temporal dead zone . For more information, consult Sect. “ The temporal dead zone ” in “Exploring ES6”. Here, I’d like to answer two questions: Why is there a temporal dead zone? Why does typeof cause a ReferenceError for a variable in the TDZ? Why is there a temporal dead zone? To catch programming errors: Being able to access a variable before its declaration is strange. If you do so, it is normally by accident and you should be warned about it. For const : Making const work properly is difficult. Quoting Allen Wirfs-Brock : “TDZs ... provide a rational semantics for const . There was significant technical discussion of that topic and TDZs emerged as the best solution.” let also has a temporal dead zone so that switching between let and const doesn...

Running a simple web server from a shell

The classic command for running a simple web server from a shell is: python -m SimpleHTTPServer [«port»] As a result, files are served at http://localhost:«port» , with 8000 being the default if you omit the port. This command has the advantage that it is built into Python and that Python is built into Mac OS X. However, this command always serves the current working directory (the directory that you are currently in), there is no way to provide a directory as an argument. That’s a problem if the directory you want to serve is constantly being deleted and recreated. Node.js doesn’t have a similar built-in mechanism, but there is an npm package that you can install: http-server . npm install -g http-server A basic way of using the shell command that this package comes with is: http-server [«path»] [-p «port»] Afterwards, files are served at http://localhost:«port» . If you omit the path, ./public is used, if it exists, and ./ otherwise. If you omit the port, 8080 is used....

Modular HTML pages

Static generation: minimizing how much is re-generated When statically generating HTML content, you face an interesting challenge: If the page frame (the “chrome” of a page) contains information that changes frequently, you need to re-generate all pages every time it does. One example of such information is a top 10 list of the pages that were most popular during the last 30 days. A work-around is to save the information in a separate file and to load that information dynamically via JavaScript. You then have a choice: You can save a JSON file and transform that into HTML or you can save an HTML file and insert it without processing it. Apart from having to re-generate fewer files, you also save traffic, because the shared information only needs to be downloaded once and will be cached, afterwards. Similar: HTTP/2 and JavaScript modules This situation is similar to JavaScript modules. Currently, many modules are bundled (combined) into a single file, to avoid the cost of one connection...

A list of ES6 feature lists

“ ECMAScript 6 Features ” by Luke Hoban “ Learn ES2015: a detailed overview of ECMAScript 6 features ” (Babel docs) “ ECMAScript 6 Cheatsheet ” by Erik Moeller “ First steps with ECMAScript 6 ” by Axel Rauschmayer Complementary and indispensable: “ ECMAScript 6 compatibility table ” by kangax.

Using the Google Analytics Core Reporting API from Node.js

This blog post explains how to use the Analytics Core Reporting API by Google from Node.js. Let’s use that API to create a Node.js script analytics.js that downloads the top 10 most visited pages of your website. Preparations You must first make sure that you can access the Google Analytics API from the script and that the appropriate library for doing so is installed. Unlocking the Google Analytics API Go to the Google Developers Console : Create a new project (e.g. myproject ). In section “APIs & auth → Credentials”, execute “Add credentials → Service account”. Download the resulting JSON file (e.g. “ myproject-3126e4caac6a.json ”). Put that file into a directory node_modules that is inside one of the parent directories of the script that we’ll create later. That means that you can keep it out of the repository with analytics.js . For example, the following path is perfectly fine: $HOME/node_modules/myproject-3126e4caac6a.json The credentials that you created have an email...

Listen to the Silences

Image
Jazz trumpeter Miles Davis, one of the greatest musicians to ever walk the planet, once said that “In music, silence is more important than sound.” I’d broaden that advice out a bit:   in life, silence is more important than the sound and fury of constant chatter in this age of instant communication.   Lately, I’ve lost the ability to hear that silence.   This is, at least in part, due to the obsessive roar of my own engines churning up that vacant space in the universe.   I need to send a message to the battlefield of everyday life:   shut up and listen! A while back, I wrote up a list of thirteen theses statements about how to live.   My hope was that the statements would offer me the opportunity to reflect on how I comport myself each day.   The list was written somewhere in the past and dutifully filed away only to be buried by more pressing matters, more words, words, words cascading and falling through my life.   Number one on this list was...

Intercepting method calls via ES6 Proxies

This blog post explains how to use ES6 Proxies to intercept method calls to an object. Read chapter “ Meta programming with proxies ” in “Exploring ES6” for more information on Proxies. The problem You can intercept the operation get (getting property values) via a proxy and you can intercept the operation apply (calling a function), but there is no single operation for method calls that you could intercept. That’s because method calls are viewed as two separate operations: First a get to retrieve a function, then an apply to call that function. The solution If you want to intercept method calls, you must therefore intercept get and return a function that intercepts the function call. The following code (which works in Firefox) demonstrates how that is done. function traceMethodCalls(obj) { let handler = { get(target, propKey, receiver) { const origMethod = target[propKey]; return function (...args) { let ...

Enumerability in ECMAScript 6

Enumerability is an attribute of object properties. This blog post explains how it works in ECMAScript 6. Let’s first explore what attributes are. Property attributes Each object has zero or more properties . Each property has a key and three or more attributes , named slots that store the data of the property (in other words, a property is itself much like a JavaScript object or a record with fields in a database). ECMAScript 6 supports the following attributes (as does ES5): All properties have the attributes: enumerable : Setting this attribute to false hides the property from some operations. configurable : Setting this attribute to false prevents several changes to a property (attributes except value can’t be change, property can’t be deleted, etc.). Normal properties (data properties, methods) have the attributes: value : holds the value of the property. writable : controls whether the property’s value can be changed. Accessors (getters/setters) have the attributes: get : hol...

Concatenating Typed Arrays

Typed Arrays don’t have a method concat() , like Arrays do. The work-around is to use the method typedArray.set(arrayOrTypedArray, offset=0) That method copies an existing Typed Array (or normal Array) into typedArray at index offset . Then you only have to make sure that typedArray is big enough to hold all (Typed) Arrays you want to concatenate: function concatenate(resultConstructor, ...arrays) { let totalLength = 0; for (let arr of arrays) { totalLength += arr.length; } let result = new resultConstructor(totalLength); let offset = 0; for (let arr of arrays) { result.set(arr, offset); offset += arr.length; } return result; } console.log(concatenate(Uint8Array, Uint8Array.of(1, 2), Uint8Array.of(3, 4))); // Uint8Array [1, 2, 3, 4]

ES6: methods versus callbacks

There is a subtle difference between an object with methods and an object with callbacks. An object whose properties are methods The this of a method is the receiver of the method call (e.g. obj if the method call is obj.m(···) ). For example, you can use the WHATWG streams API as follows: let surroundingObject = { surroundingMethod() { let obj = { data: 'abc', start(controller) { ··· console.log(this.data); // abc (*) this.pull(); // (**) ··· }, pull() { ··· }, cancel() { ··· }, }; let stream = new ReadableStream(obj); }, }; That is, obj is an object whose properties start , pull and cancel are methods. Accordingly, these methods can use this to access object-local state (line *) an...