js in the open
DESCRIPTION
TRANSCRIPT
JS in the open(or JS in the wild)
Friday, November 9, 12
@victorporof
Programmer at Mozilla
Friday, November 9, 12
The JavaScript you probably know
Friday, November 9, 12
Number
String
Boolean
Object (Function, Array, Date, RegExp ...)
Function
Null
Undefined
Friday, November 9, 12
typeof 3 == “number”
typeof “Gangnam Style” == “string”
typeof false == “boolean”
typeof document == “object”
typeof document.getElementById == “object”
typeof null == “object”
typeof undefined == “undefined”
Friday, November 9, 12
new Number(3)
new String(“Gangnam Style”)
new Boolean(false)
Friday, November 9, 12
typeof new Number(3) == “object”
typeof new String(“Gangnam Style”) == “object”
typeof new Boolean(false) == “object”
Friday, November 9, 12
typeof new Number(3) == “object”
typeof new String(“Gangnam Style”) == “object”
typeof new Boolean(false) == “object”
Constructors
Friday, November 9, 12
JavaScript is fundamentally about Objects
Friday, November 9, 12
The JavaScript you probably don’t know
Friday, November 9, 12
Friday, November 9, 12
2006
Functional collectors
Array extras
Array and String generics
for each..in loops
new in JavaScript 1.6
Friday, November 9, 12
Functional collectors
every(), filter(), forEach(), map(), some()
new in JavaScript 1.6
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
Functional collectors
every(), filter(), forEach(), map(), some()
new in JavaScript 1.6
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
Array extras
indexOf(), lastIndexOf()
new in JavaScript 1.6
var array = [2, 5, 9, 2];var index = array.lastIndexOf(2);// index is 3index = array.lastIndexOf(7);// index is -1index = array.lastIndexOf(2, 3);// index is 3index = array.lastIndexOf(2, 2);// index is 0index = array.lastIndexOf(2, -1);// index is 3
Friday, November 9, 12
Array and String generics
new in JavaScript 1.6
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
for each..in loops
new in JavaScript 1.6
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
for each..in loops
new in JavaScript 1.6
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
2007
Generators
Iterators
Array comprehensions
let statements, expressions, definitions
destructuring assignment
multiple value returns & looping across objects
new in JavaScript 1.7
Friday, November 9, 12
Generators
new in JavaScript 1.7
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
Iterators
new in JavaScript 1.7
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
Array comprehensions
new in JavaScript 1.7
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
let definitions
new in JavaScript 1.7
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
let definitions
new in JavaScript 1.7
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
let statements and expressions
new in JavaScript 1.7
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 = 27console.log(x + y); // 5 + 0 = 5
Friday, November 9, 12
destructuring assignment
new in JavaScript 1.7
var array = [1, 2, 3];var [fir, sec, thi] = array; // fir = 1, sec = 2, thi = 3var [, 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
destructuring assignment
new in JavaScript 1.7
var a = 1;var b = 3; [a, b] = [b, a];
Friday, November 9, 12
multiple value returns
new in JavaScript 1.7
function f() { return [1, 2];}
var [a, b] = f();console.log("A is " + a + " B is " + b);
Friday, November 9, 12
multiple value returns
new in JavaScript 1.7
function f() { return { a: 1, b: 3 };}
var [a, b] = f();console.log("A is " + a + " B is " + b);
Friday, November 9, 12
looping across objects
new in JavaScript 1.7
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
2008
expression closures
getters and setters
generator expressions
more Array extras
new in JavaScript 1.8
Friday, November 9, 12
expression closures
new in JavaScript 1.8
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
expression closures
(short function syntax, strawman)
new in JavaScript 1.8
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
getters and setters
new in JavaScript 1.8
var object = { _a: 7, get a() { return this._a + 1; }, set a(x) { this._a = x / 2; }};
Friday, November 9, 12
getters and setters
new in JavaScript 1.8
var object = { _a: 7, get a() this._a + 1, set a(x) this._a = x / 2};
Friday, November 9, 12
generator expressions
new in JavaScript 1.8
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
generator expressions
new in JavaScript 1.8
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
more Array extras
reduce(), reduceRight()
new in JavaScript 1.8
var total = [0, 1, 2, 3].reduce(function(a, b) { return a + b;});// total == 6
Friday, November 9, 12
more Array extras
reduce(), reduceRight()
new in JavaScript 1.8
var total = [0, 1, 2, 3].reduce(function(a, b) a + b);
Friday, November 9, 12
2009 ... ?
nicer Object API
default function params, rest params
for..of loops
WeakMaps, Maps, Sets
strict mode
ES5 to ES6 and beyond
Friday, November 9, 12
Nicer Object APIvar 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
Nicer Object API// Shape - classfunction 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(); // instantiateshape.move(); // "Shape moved."
Friday, November 9, 12
Nicer Object API// Shape - superclassfunction Shape() { // Shape constructor this.x = 0; this.y = 0;}Shape.prototype.move = function() { this.x += 10; this.y += 10; console.info("Shape moved.");};
// Rectangle - subclassfunction Rectangle() { // Rectangle constructor Shape.call(this); // call super constructor}Rectangle.prototype = Object.create(Shape.prototype); // inherit methodsRectangle.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(); // instantiaterect instanceof Rectangle // truerect.move(); // "Shape moved."rect.moveAt(5, 2); // "Shape moved at: 5, 2"
Friday, November 9, 12
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 5fun(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
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
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); // truemySet.has(3); // false, 3 has not been added to the setmySet.has(5); // truemySet.has(Math.sqrt(25)); // truemySet.has("Some Text".toLowerCase()); // truemySet.size; // 3 mySet.delete(5); // removes 5 from the setmySet.has(5); // false, 5 has been removedmySet.size; // 2, we just removed one value // iterate over items in setfor (let item of mySet) console.log(item);// logs the items in the order: 1, "some text"
// convert set to plain Arrayvar myArr = [v for (v of mySet)]; // [1, "some text"]
Friday, November 9, 12
Maps vs. Weak Maps// Maps are key/value collections in which keys are objects.var myMap = new Map(); // setting the valuesmyMap.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 valuesmyMap.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 mapfor (let [key, value] of mySet) console.log(value);
Friday, November 9, 12
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
in a galaxy far far away ...
quasi-literals
thin and fat arrow functions with lexical this binding
triangle operator
modules
classes
ParallelArray
Harmony vs. Strawman
Friday, November 9, 12
in a galaxy far far away ...
Paren-free
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
Rhino Unicorn
https://brendaneich.com/
Friday, November 9, 12
Design patterns
Friday, November 9, 12
We won’t talk about design patters
Friday, November 9, 12
avoid defensive programming
premature optimization is evil
over-complicating things is eviler
over-engineering is the evilest
Friday, November 9, 12
Friday, November 9, 12
What we use at Mozilla
Friday, November 9, 12
What we use at Mozilla
and you should too
Friday, November 9, 12
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
MyNamespace.Fox = function(aName, aYearsOld) { this.name = aName; this.yearsOld = aYearsOld;};
MyNamespace.Fox.prototype = { run: function(param) { }, sleep: function() { }};
var pinky = new Fox("Pinky", 10);var leyla = new Fox("Leyla", 7);leyla.cuteness = 5;
OOP
constructors!
Friday, November 9, 12
MyNamespace.Fox = function(aName, aYearsOld) { this.name = aName; this.yearsOld = aYearsOld;};
MyNamespace.Fox.prototype = { run: function(param) { }, sleep: function() { }};
var pinky = new Fox("Pinky", 10);var leyla = new Fox("Leyla", 7);leyla.cuteness = 5;
OOP
private members?
Friday, November 9, 12
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
function foo(a, b){ function bar() { return a + b; }
return bar();}
function foo2(a, b){ function bar(c) { return a + b + c; }
return bar;}
Closures!
var res1 = foo(5, 2);
var res2 = foo2(5, 2);
var res3 = res2(3);
Friday, November 9, 12
function foo(a, b){ function bar() { return a + b; }
return bar();}
function foo2(a, b){ function bar(c) { return a + b + c; }
return bar;}
Closures!
var res1 = foo(5, 2);// returns 7
var res2 = foo2(5, 2);// returns a closure function
var res3 = res2(3);// returns 7
Friday, November 9, 12
MyNamespace.Fox = function(aName, aYearsOld) { this.name = aName; this.yearsOld = aYearsOld;};
MyNamespace.Fox.prototype = { run: function(param) { }, sleep: function() { }};
var pinky = new Fox("Pinky", 10);var leyla = new Fox("Leyla", 7);leyla.cuteness = 5;
leyla.yearsOld; // 7
OOP
private members?
Friday, November 9, 12
MyNamespace.Fox = function(aName, aYearsOld) { this._name = aName; this._yearsOld = aYearsOld;};
MyNamespace.Fox.prototype = { run: function(param) { }, sleep: function() { }};
var pinky = new Fox("Pinky", 10);var leyla = new Fox("Leyla", 7);leyla.cuteness = 5;
leyla._yearsOld; // 7
OOP
we just _prefix them...and respect it
Friday, November 9, 12
OOPMyNamespace.Fox = function(aName, aYearsOld) { var name = aName; var yearsOld = aYearsOld;
this.run = function(param) { }; this.sleep = function() { };};
var pinky = new Fox("Pinky", 10);var leyla = new Fox("Leyla", 7);leyla.cuteness = 5;
leyla.yearsOld; // undefined
you can have private members...if you really want to
Friday, November 9, 12
OOPMyNamespace.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
// Shape - superclassfunction Shape() { // Shape constructor this.x = 0; this.y = 0;}Shape.prototype.move = function() { this.x += 10; this.y += 10; console.info("Shape moved.");};
// Rectangle - subclassfunction Rectangle() { // Rectangle constructor Shape.call(this); // call super constructor}Rectangle.prototype = Object.create(Shape.prototype); // inherit methodsRectangle.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(); // instantiaterect instanceof Rectangle // truerect.move(); // "Shape moved."rect.moveAt(5, 2); // "Shape moved at: 5, 2"
OOP
we generally take it easy :)
Friday, November 9, 12
let observer = { observe: function(aSubject, aTopic, aData) { if (aTopic == "some-topic") { window.dump("Data received: " + aData); } } };
// observer for a notificationServices.obs.addObserver(observer, "some-topic", false);
// stop observingServices.obs.removeObserver(observer, "some-topic");
// somewhere, somebody does this:observerService.notifyObservers(someObject, "some-topic", "some-data");
Observers
Friday, November 9, 12
XPCOMUtils.defineLazyGetter(myObject, "someProperty", function() { // do some heavy duty stuff // ... return something;});
// avoid disk activity, load modules only when neededXPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource:///modules/FileUtils.jsm");
Lazy getters
Friday, November 9, 12
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
Debugging JavaScript in Firefox
(demo)
Friday, November 9, 12