<canvas>
performance
<label>
<input type="checkbox"
onchange="sessionStorage.insurance = checked">
I want insurance on this trip.
</label>
if (sessionStorage.insurance) { ... }
<p>You have viewed this page <span id="count">an untold number of</span> time(s).</p> <script> var storage = globalStorage['example.com']; if (!storage.viewCount) storage.viewCount = 0; storage.viewCount = parseInt(storage.viewCount) + 1; $('count').textContent = storage.viewCount; </script>
The script element was used on roughly half the pages we checked. The most common attributes: language src type defer charset id fptype for event name langauge class tppabs langugage languaje
.
As you might expect, Javascript book sales are up 121%, driven by the new interest in AJAX. (We don't yet track Ajax as a separate category, choosing instead to include it with Javascript.)
let
blocks: let n=len(); for (let i=0; i<n; i++) ...
[title, detail, size] = s.parseJSON();
for (i in array_iterator(nodelist)) ...
function fib() {
let [i, j] = [0, 1];
while (true) {
yield i; [i, j] = [j, i + j];
}
}
squares = [i * i for (i in count(n)];
function Point(x, y) { return { getX: function () { return x }, getY: function () { return y } } } for (var i = 0, a = []; i < 1e5; i++) a[i] = new Point(i, i)
function Point1(x, y) { this.x = x this.y = y }
private internal public
)
Object Array Function Boolean Number String Date RegExp ...Error
int uint double decimal Type *
false == new Boolean(false)
false === new Boolean(false)
42 === new Number(42)
"foo" === new String("foo")
var x : String; // defaults to null
var x : String = y; // y converts to string
var x : SubType = y; // downcast y, may throw
function f(a : int, b : String, c : Object) : RetType { // arguments are guaranteed to match types // return value must convert to or match RetType }
function f(a : int, b : String, ...rest) {
// rest is of type Array, contains actual trailing arguments
}
List.<T>
for a List
with items of type T
{p: T, q: U}
where T
and U
are type expressions
[T, U, V]
where any elements after index 2 are also of type V
function (this: T, a: U, b: V): R
Object!
does not include null
Number?
is the nullable number type
Object
if no superclass is given
class C extends B { function C(m) { mem = m } public function getmem() { return mem } private var mem : Object } var c : C = new C(new Date)
C.prototype
exists, but c.getmem()
always refers to the declared class method
interface I {
function meth(int) : int
}
implement
one or more interfaces, meaning it supplies function definitions for all interface methods
class B implements I {
public function meth(a : int) : int { return a * a }
}
type Q = {p: int, q: String} type R = {p: int, q: String, r: Boolean}
type A = [int, String, Boolean, Object]
type F = function (int, String, Boolean): Object type G = function (int, Object, Object): Number
R
is a subtype of Q
and G
is a subtype of F
type U = (R, A, F)
U
is a union: any value in U
must be an R
, A
, or F
switch type
statement selects the dynamic type of a value of union (or any) type
public
, private
, internal
, intrinsic
namespace improved
class C {
public function frob(): int {...}
improved function frob(alpha: double): double { ... }
}
c.improved::frob(1.2)
use namespace improved
. . . c.frob(alpha)
package org.mozilla.venkman {
class Debugger { . . . }
class Inspector { . . . }
class StackWalker { . . . }
}
import org.mozilla.venkman.* // use Debugger, Inspector, etc. freely
import org.mozilla.venkman.Inspector // Use Inspector without qualification
let
as a "better var
":
function f(v1: Vec3, v2: Vec3) { if (cross_product_only) { let a1 = v1[0], a2 = v1[1], a3 = v1[2] let b1 = v2[0], b2 = v2[1], b3 = v2[2] return new Vec3(a2*b3 - a3*b2, a3*b1 - a1*b3, a1*b2 - a2*b1) } . . . }
let
variables have block scope
for
loops contain an implicit block
for (let i = 0; i < n; i++) sum += a[i] for (let key in obj) print(key, obj[key])
(function (a, b) {
var x = b, y = a
var z = eval(s)
commit(x, y, z)
})(x, y)
let (x = y, y = x, z) {
z = eval(s)
commit(x, y, z)
}
return (function (a, b) {
var x = b, y = a
return commit(x, y, eval(s))
})(x, y)
return let (x = y, y = x, z) commit(x, y, eval(s))
let
variables are scoped to the expression
// swap, rotate, permute in general [a, b] = [b, a] [p, q, r] = [q, r, p] // destructure a triple into fresh vars var [s, v, o] = db.getTriple()
let {'Title': title, 'Height': height, 'Width': width} = jsonResult
for-in
loops:
for (let [key, {'Title':title, 'FileSize':size}] in dict) print(key, title, size)
let it = Iterator(["meow", "oink", "woof"])
it.next() returns [0, "meow"]
it.next() returns [1, "oink"]
it.next() returns [2, "woof"]
it.next() throws StopIteration
The for-in
loop catches StopIteration
for you:
for (let i in it) print(i) // no try-catch needed
Generators
yield
in a function makes a generator:
function count(n : int) {
for (let i = 0; i < n; i++)
yield i
}
- A generator function returns an iterator:
var gen = count(10)
gen.next() returns 0; . . .; gen.next() returns 9
gen.next() throws StopIteration
gen.send(value)
passes value
back to yield
gen.throw(exception)
throws exception
from yield
Array Comprehensions
- Sugar for initializing an
Array
from iterators
let squares = [i * i for (i in count(10))]
print(squares) => "0,1,4,9,...,81"
let odd_squares = [i * i for (i in count(10)) if (i % 2)]
return [i * j for (i in it1) for (j in it2) if (i != j)]
Operators
- Much-requested ability to customize operators by type
- Does not require dispatching based on argument type
- Example showing binary vs. unary operator handling:
class Complex {
var real:Number, imag:Number;
public static function +(a:Object, b:Object):Complex {
if (a is Complex && b is Complex)
return new Complex(a.real + b.real, a.imag + b.imag)
if (b == null)
return (a is Complex) ? a : new Complex(a)
return intrinsic::+(a, b)
}
. . .
}
Decimal
print(79.49 - 35.99) => 43.49999999999999
- "JavaScript math is broken" (it's the same as Java, C, etc.)
- Most-duplicated bug at https://bugzilla.mozilla.org
- Solution: new
decimal
type and pragma to use it
{
use decimal
print(79.49 - 35.99) // => 43.50
}
- Enough precision to represent all normalized
doubles
- Tracking IEEE 754r
Miscellany
- A built-in, extensible JSON encoder and decoder
- Object getters, setters, and "catch-alls":
return {
get x() { return this.inner.x },
set x(nx) { this.inner.x = nx },
get *(id) { return this.intrinsic::get(id) },
set *(id,v) { return this.intrinsic::set(id, v) },
}
- Standard
Date.parse
format based on ISO 8601
let today = Date.parse("2006-10-25T");
- Slice operators:
s[i:j]
, a[-5:-2]
- Slice step:
reversed = array[::-1], evens = nums[i:j:2];
Bug Fixes
-
arguments
delegates to Array.prototype
- Inner function
this
binds to outer this
by default
- Standard global properties (Date, String, etc.) immutable
-
new RegExp("pattern")
same as /pattern/
- Allow a trailing comma in object initialisers
- s[i] for fast/guaranteed s.charAt(i) alternative
-
map
and other generic functions on Array-likes
The Near Term
- Access to the ECMA TG1 wiki in June 2006
- JS1.7 in Firefox 2 released yesterday
let
blocks
- Destructuring assignment
- Iterators
- Generators
- Array comprehensions
- JS1.8 in Firefox 3 pretty soon (2007)
- ECMAScript Edition 4 spec deadline: end of Q1 2007
- JS2 based on final ES4 spec in Mozilla, in 2007
The Future of JavaScript
- Web browsers under increasing size constraints
- JS likely to remain the default/only browser programming language
- JS2 will displace JS1 eventually (~4 years?)
- JS2 must be strong enough for the long run
- Small dynamic prototypes
- Programming in the large support
- Optimized for space and speed
- Extensible enough to forestall JS3000
- Security through virtual machine (VM) techniques
The Future of the Web
- Browsers are runtimes for JS + HTML/CSS + XML
- JS2 + XBL2 support new XML languages
- With the right low-level rendering APIs
- And sufficient runtime and memory performance
- Which is coming in the form of JITed JS VMs
- VMs provide better security models/guarantees
- JS is good enough for a lot, but not for the future
- JS2 is vital to the future of the Web
Finis