12. new in JavaScript 1.6
2006
Functional collectors
Array extras
Array and String generics
for each..in loops
Friday, November 9, 12
13. new in JavaScript 1.6
Functional collectors
every(), filter(), forEach(), map(), some()
function isBigEnough(element, index, array) {
return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
var passed = [12, 54, 18, 130, 44].every(isBigEnough);
// passed is true
Friday, November 9, 12
14. new in JavaScript 1.6
Functional collectors
every(), filter(), forEach(), map(), some()
function fuzzyPlural(single) {
var result = single.replace(/o/g, 'e');
return result;
}
var words = ["foot", "goose", "moose", "kangaroo"];
console.log(words.map(fuzzyPlural));
// ["feet", "geese", "meese", "kangaree"]
Friday, November 9, 12
15. new in JavaScript 1.6
Array extras
indexOf(), lastIndexOf()
var array = [2, 5, 9, 2];
var index = array.lastIndexOf(2);
// index is 3
index = array.lastIndexOf(7);
// index is -1
index = array.lastIndexOf(2, 3);
// index is 3
index = array.lastIndexOf(2, 2);
// index is 0
index = array.lastIndexOf(2, -1);
// index is 3
Friday, November 9, 12
16. new in JavaScript 1.6
Array and String generics
function isLetter(character) {
return (character >= "a" && character <= "z");
}
if (Array.prototype.every.call(str, isLetter)) {
alert("The string '" + str + "' contains only letters!");
}
Friday, November 9, 12
17. new in JavaScript 1.6
for each..in loops
var sum = 0;
var obj = { prop1: 5, prop2: 13, prop3: 8 };
for (var item in obj) {
sum += item;
}
print(sum); // prints 0prop1prop2prop3
Friday, November 9, 12
18. new in JavaScript 1.6
for each..in loops
var sum = 0;
var obj = { prop1: 5, prop2: 13, prop3: 8 };
for each (var item in obj) {
sum += item;
}
print(sum); // prints "26", which is 5+13+8
Friday, November 9, 12
19. new in JavaScript 1.7
2007
Generators
Iterators
Array comprehensions
let statements, expressions, definitions
destructuring assignment
multiple value returns & looping across objects
Friday, November 9, 12
20. new in JavaScript 1.7
Generators
function fib() {
var i = 0, j = 1;
while (true) {
yield i;
var t = i;
i = j;
j += t;
}
}
var g = fib();
for (var i = 0; i < 10; i++) {
console.log(g.next());
}
Friday, November 9, 12
21. new in JavaScript 1.7
Iterators
var obj = {
name: "Jack Bauer",
username: "JackB",
id: 12345,
agency: "CTU",
region: "Los Angeles"
};
obj.__iterator__ = function() {
for (let item in this) {
if (item != "id") { yield this[item]; }
}
};
for (let item in obj) {
alert(item);
}
Friday, November 9, 12
22. new in JavaScript 1.7
Array comprehensions
function range(begin, end) {
for (let i = begin; i < end; ++i) {
yield i;
}
}
var ten_squares = [i * i for each (i in range(0, 10))];
var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
Friday, November 9, 12
23. new in JavaScript 1.7
let definitions
for (var i = 0; i < 10; i++) {
console.log(i); // prints 0, 1, 2 ... 9
}
console.log(i); // prints 10
for (let i = 10; i < 100; i++) {
console.log(i); // prints 10, 11, 12 ... 99
}
console.log(i); // prints 10
Friday, November 9, 12
24. new in JavaScript 1.7
let definitions
function varTest() {
var x = 31;
if (true) {
var x = 71; // same variable!
alert(x); // 71
}
alert(x); // 71
}
function letTest() {
let x = 31;
if (true) {
let x = 71; // different variable
alert(x); // 71
}
alert(x); // 31
}
Friday, November 9, 12
25. new in JavaScript 1.7
let statements and expressions
var x = 5;
var y = 0;
let (x = x + 10, y = 12) {
console.log(x + y); // 15 + 12 = 27
}
console.log(x + y); // 5 + 0 = 5
var x = 5;
var y = 0;
console.log(let (x = x + 10, y = 12) x + y); // 15 + 12 = 27
console.log(x + y); // 5 + 0 = 5
Friday, November 9, 12
26. new in JavaScript 1.7
destructuring assignment
var array = [1, 2, 3];
var [fir, sec, thi] = array; // fir = 1, sec = 2, thi = 3
var [, x] = array; // x = 2
var obj = {
name: "Jack Bauer",
username: "JackB",
id: 12345,
agency: "CTU",
region: "Los Angeles"
};
var [name, agency, region] = obj;
// name = "Jack Bauer", agency = "CTU", region = "Los Angeles"
Friday, November 9, 12
27. new in JavaScript 1.7
destructuring assignment
var a = 1;
var b = 3;
[a, b] = [b, a];
Friday, November 9, 12
28. new in JavaScript 1.7
multiple value returns
function f() {
return [1, 2];
}
var [a, b] = f();
console.log("A is " + a + " B is " + b);
Friday, November 9, 12
29. new in JavaScript 1.7
multiple value returns
function f() {
return { a: 1, b: 3 };
}
var [a, b] = f();
console.log("A is " + a + " B is " + b);
Friday, November 9, 12
30. new in JavaScript 1.7
looping across objects
var obj = {
name: "Jack Bauer",
username: "JackB",
id: 12345,
agency: "CTU",
region: "Los Angeles"
};
obj.__iterator__ = function() {
for (let item in this) {
if (item != "id") { yield [item, this[item]]; }
}
};
for (let [item, value] in obj) {
alert(item + ": " + value);
}
Friday, November 9, 12
31. new in JavaScript 1.8
2008
expression closures
getters and setters
generator expressions
more Array extras
Friday, November 9, 12
32. new in JavaScript 1.8
expression closures
function(x) { return x * x; }
// vs.
function(x) x * x
var passed = [12, 5, 8, 130, 44].every(function(e) e >= 10);
// passed is false
var passed = [12, 54, 18, 130, 44].every(function(e) e >= 10);
// passed is true
Friday, November 9, 12
33. new in JavaScript 1.8
expression closures
(short function syntax, strawman)
function(x) { return x * x; }
// vs.
ƒ(x) x * x
[12, 5, 8, 130, 44].map(ƒ(e) e / 2);
// divide all values by 2
[12, 54, 18, 130, 44].map(ƒ(e) e % 2 ? true : false );
// map odds and evens
Friday, November 9, 12
34. new in JavaScript 1.8
getters and setters
var object = {
_a: 7,
get a() { return this._a + 1; },
set a(x) { this._a = x / 2; }
};
Friday, November 9, 12
35. new in JavaScript 1.8
getters and setters
var object = {
_a: 7,
get a() this._a + 1,
set a(x) this._a = x / 2
};
Friday, November 9, 12
36. new in JavaScript 1.8
generator expressions
function add3(obj) {
for (let i in obj) yield obj[i] + 3;
}
let it = add3([1, 2, 3]);
try {
while (true) {
alert(it.next());
}
} catch (err if err instanceof StopIteration) {
alert("End of record.");
}
Friday, November 9, 12
37. new in JavaScript 1.8
generator expressions
let it = (i + 3 for (i of [1, 2, 3]));
try {
while (true) {
alert(it.next());
}
} catch (err if err instanceof StopIteration) {
alert("End of record.");
}
Friday, November 9, 12
38. new in JavaScript 1.8
more Array extras
reduce(), reduceRight()
var total = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
});
// total == 6
Friday, November 9, 12
39. new in JavaScript 1.8
more Array extras
reduce(), reduceRight()
var total = [0, 1, 2, 3].reduce(function(a, b) a + b);
Friday, November 9, 12
40. ES5 to ES6 and beyond
2009 ... ?
nicer Object API
default function params, rest params
for..of loops
WeakMaps, Maps, Sets
strict mode
Friday, November 9, 12
41. Nicer Object API
var obj1 = {
name: "Jack Bauer",
username: "JackB",
id: 12345,
agency: "CTU",
region: "Los Angeles"
};
var obj2 = Object.create(obj1, {
foo: {
value: "hello",
writable: true, // value may be changed
configurable: true // property may be changed or deleted
},
bar: {
enumerable: false, // shows up during enumeration
get: function() { return 10 },
set: function(value) { alert("Setting 'o.bar' to", value);
}
});
Friday, November 9, 12
42. Nicer Object API
// Shape - class
function Shape() { // Shape constructor
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function() {
this.x += 10;
this.y += 10;
console.info("Shape moved.");
};
var shape = new Shape(); // instantiate
shape.move(); // "Shape moved."
Friday, November 9, 12
43. Nicer Object API
// Shape - superclass
function Shape() { // Shape constructor
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function() {
this.x += 10;
this.y += 10;
console.info("Shape moved.");
};
// Rectangle - subclass
function Rectangle() { // Rectangle constructor
Shape.call(this); // call super constructor
}
Rectangle.prototype = Object.create(Shape.prototype); // inherit methods
Rectangle.prototype.moveAt = function(x, y) { // define new methods
this.x += x;
this.y += y;
console.info("Shape moved at: " + x + ", " + y);
};
var rect = new Rectangle(); // instantiate
rect instanceof Rectangle // true
rect.move(); // "Shape moved."
rect.moveAt(5, 2); // "Shape moved at: 5, 2"
Friday, November 9, 12
44. Default and rest params
// when called, if no value or undefined is passed as second argument,
// b will have 1 as value.
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
function fun(a, b, ...theArgs) {
for (let arg of theArgs) console.log(arg);
}
fun(1, 2);
fun(1, 2, 5); // logs 5
fun(1, 2, 5, 6, 7); // logs 5, 6, 7
function sortRestArgs(x, ...someStuff) {
return someStuff.sort();
}
console.log(sortRestArgs(0, 5, 3, 7, 1)); // logs 1, 3, 5, 7
Friday, November 9, 12
45. for..of loops
let arr = [ 3, 5, 7 ];
arr.foo = "hello";
for (let i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
for (let i of arr) {
console.log(i); // logs "3", "5", "7"
}
for (let paragraph of document.querySelectorAll("article > p")) {
paragraph.classList.add("read");
}
Friday, November 9, 12
46. Sets
// Sets are collections in which values are unique.
var mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add("some text");
mySet.has(1); // true
mySet.has(3); // false, 3 has not been added to the set
mySet.has(5); // true
mySet.has(Math.sqrt(25)); // true
mySet.has("Some Text".toLowerCase()); // true
mySet.size; // 3
mySet.delete(5); // removes 5 from the set
mySet.has(5); // false, 5 has been removed
mySet.size; // 2, we just removed one value
// iterate over items in set
for (let item of mySet) console.log(item);
// logs the items in the order: 1, "some text"
// convert set to plain Array
var myArr = [v for (v of mySet)]; // [1, "some text"]
Friday, November 9, 12
47. Maps vs. Weak Maps
// Maps are key/value collections in which keys are objects.
var myMap = new Map();
// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");
myMap.size; // 3
// getting the values
myMap.get(keyString); // "value associated with 'a string'"
myMap.get(keyObj); // "value associated with keyObj"
myMap.get(keyFunc); // "value associated with keyFunc"
myMap.get("a string"); // "value associated with 'a string'"
myMap.set(0, "positive zero");
myMap.get(-0); // "negative zero"
myMap.set(-0, "negative zero");
myMap.get(0); // "positive zero"
// iterate over items in map
for (let [key, value] of mySet) console.log(value);
Friday, November 9, 12
48. Strict mode
"use strict";
mistypedVariable = 17;
// throws a ReferenceError
delete Object.prototype;
// throws a TypeError
var f = function() { return arguments.callee; };
f(); // throws a TypeError
var o = { p: 1, p: 2 };
// syntax error
function sum(a, a, c) { return a + a + c; }
// syntax error
function that() { return this; }
that(); // undefined
Friday, November 9, 12
49. Harmony vs. Strawman
in a galaxy far far away ...
quasi-literals
thin and fat arrow functions with lexical this binding
triangle operator
modules
classes
ParallelArray
Friday, November 9, 12
50. Paren-free
in a galaxy far far away ...
if year > 2010 {
syntax++
}
for i in iter {
frob(i)
}
while lo <= hi {
let mid = (lo + hi) / 2
}
... return [i * i for i in range(n)]
Friday, November 9, 12
51. Rhino Unicorn
https://brendaneich.com/
Friday, November 9, 12
55. We won’t talk about design patters
Friday, November 9, 12
56. avoid defensive programming
premature optimization is evil
over-complicating things is eviler
over-engineering is the evilest
Friday, November 9, 12
59. What we use at Mozilla
and you should too
Friday, November 9, 12
60. OOP
MyNamespace.Fox = function() {
this.name = "";
this.yearsOld = 0;
};
MyNamespace.Fox.prototype = {
run: function(param) {
},
sleep: function() {
}
};
var pinky = new Fox();
var leyla = new Fox();
leyla.cuteness = 5;
Friday, November 9, 12
61. OOP
MyNamespace.Fox = function(aName, aYearsOld) {
this.name = aName;
this.yearsOld = aYearsOld;
};
MyNamespace.Fox.prototype = { constructors!
run: function(param) {
},
sleep: function() {
}
};
var pinky = new Fox("Pinky", 10);
var leyla = new Fox("Leyla", 7);
leyla.cuteness = 5;
Friday, November 9, 12
62. OOP
MyNamespace.Fox = function(aName, aYearsOld) {
this.name = aName;
this.yearsOld = aYearsOld;
};
MyNamespace.Fox.prototype = { private members?
run: function(param) {
},
sleep: function() {
}
};
var pinky = new Fox("Pinky", 10);
var leyla = new Fox("Leyla", 7);
leyla.cuteness = 5;
Friday, November 9, 12
63. Closures!
function foo(a, b){
function bar() {
return a + b;
}
return bar();
}
function foo2(a, b){
function bar(c) {
return a + b + c;
}
return bar;
}
Friday, November 9, 12
64. Closures!
function foo(a, b){
function bar() {
return a + b;
}
var res1 = foo(5, 2);
return bar();
}
var res2 = foo2(5, 2);
function foo2(a, b){
function bar(c) { var res3 = res2(3);
return a + b + c;
}
return bar;
}
Friday, November 9, 12
65. Closures!
function foo(a, b){
function bar() {
return a + b;
}
var res1 = foo(5, 2);
return bar(); // returns 7
}
var res2 = foo2(5, 2);
// returns a closure function
function foo2(a, b){
function bar(c) { var res3 = res2(3);
return a + b + c; // returns 7
}
return bar;
}
Friday, November 9, 12
66. OOP
MyNamespace.Fox = function(aName, aYearsOld) {
this.name = aName;
this.yearsOld = aYearsOld;
};
MyNamespace.Fox.prototype = {
run: function(param) {
}, private members?
sleep: function() {
}
};
var pinky = new Fox("Pinky", 10);
var leyla = new Fox("Leyla", 7);
leyla.cuteness = 5;
leyla.yearsOld; // 7
Friday, November 9, 12
67. OOP
MyNamespace.Fox = function(aName, aYearsOld) {
this._name = aName;
this._yearsOld = aYearsOld;
};
MyNamespace.Fox.prototype = {
run: function(param) {
}, we just _prefix them
sleep: function() {
} ...and respect it
};
var pinky = new Fox("Pinky", 10);
var leyla = new Fox("Leyla", 7);
leyla.cuteness = 5;
leyla._yearsOld; // 7
Friday, November 9, 12
68. OOP
MyNamespace.Fox = function(aName, aYearsOld) {
var name = aName;
var yearsOld = aYearsOld;
this.run = function(param) {
};
this.sleep = function() {
}; you can have private members
};
...if you really want to
var pinky = new Fox("Pinky", 10);
var leyla = new Fox("Leyla", 7);
leyla.cuteness = 5;
leyla.yearsOld; // undefined
Friday, November 9, 12
69. OOP
MyNamespace.Fox = function(aName, aYearsOld) {
var name = aName;
var yearsOld = aYearsOld;
this.run = function(param) {
};
this.sleep = function() {
};
Object.defineProperty(this, "yearsOld", {
get: function() { return yearsOld * 6; }
set: function(value) { yearsOld = value; }
});
};
var pinky = new Fox("Pinky", 10);
var leyla = new Fox("Leyla", 7);
leyla.cuteness = 5;
leyla.yearsOld; // 42
Friday, November 9, 12
70. OOP
// Shape - superclass
function Shape() { // Shape constructor
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function() {
this.x += 10;
this.y += 10;
console.info("Shape moved.");
};
we generally take it easy :)
// Rectangle - subclass
function Rectangle() { // Rectangle constructor
Shape.call(this); // call super constructor
}
Rectangle.prototype = Object.create(Shape.prototype); // inherit methods
Rectangle.prototype.moveAt = function(x, y) { // define new methods
this.x += x;
this.y += y;
console.info("Shape moved at: " + x + ", " + y);
};
var rect = new Rectangle(); // instantiate
rect instanceof Rectangle // true
rect.move(); // "Shape moved."
rect.moveAt(5, 2); // "Shape moved at: 5, 2"
Friday, November 9, 12
71. Observers
let observer = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "some-topic") {
window.dump("Data received: " + aData);
}
}
};
// observer for a notification
Services.obs.addObserver(observer, "some-topic", false);
// stop observing
Services.obs.removeObserver(observer, "some-topic");
// somewhere, somebody does this:
observerService.notifyObservers(someObject, "some-topic", "some-data");
Friday, November 9, 12
72. Lazy getters
XPCOMUtils.defineLazyGetter(myObject, "someProperty", function() {
// do some heavy duty stuff
// ...
return something;
});
// avoid disk activity, load modules only when needed
XPCOMUtils.defineLazyModuleGetter(this,
"FileUtils", "resource:///modules/FileUtils.jsm");
Friday, November 9, 12
73. Debugger API + Scratchpad
(demo)
https://developer.mozilla.org/en-US/docs/Tools/Scratchpad
https://wiki.mozilla.org/Debugger
https://developer.mozilla.org/en-US/docs/JavaScript
Friday, November 9, 12