Js in the open

Preview:

DESCRIPTION

 

Citation preview

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

https://brendaneich.com/

Friday, November 9, 12

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

Debugging JavaScript in Firefox

(demo)

Friday, November 9, 12

Recommended