Top Banner
JS in the open (or JS in the wild) Friday, November 9, 12
74
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Js in the open

JS in the open(or JS in the wild)

Friday, November 9, 12

Page 2: Js in the open

@victorporof

Programmer at Mozilla

Friday, November 9, 12

Page 3: Js in the open

The JavaScript you probably know

Friday, November 9, 12

Page 4: Js in the open

Number

String

Boolean

Object (Function, Array, Date, RegExp ...)

Function

Null

Undefined

Friday, November 9, 12

Page 5: Js in the open

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

Page 6: Js in the open

new Number(3)

new String(“Gangnam Style”)

new Boolean(false)

Friday, November 9, 12

Page 7: Js in the open

typeof new Number(3) == “object”

typeof new String(“Gangnam Style”) == “object”

typeof new Boolean(false) == “object”

Friday, November 9, 12

Page 8: Js in the open

typeof new Number(3) == “object”

typeof new String(“Gangnam Style”) == “object”

typeof new Boolean(false) == “object”

Constructors

Friday, November 9, 12

Page 9: Js in the open

JavaScript is fundamentally about Objects

Friday, November 9, 12

Page 10: Js in the open

The JavaScript you probably don’t know

Friday, November 9, 12

Page 11: Js in the open

Friday, November 9, 12

Page 12: Js in the open

2006

Functional collectors

Array extras

Array and String generics

for each..in loops

new in JavaScript 1.6

Friday, November 9, 12

Page 13: Js in the open

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

Page 14: Js in the open

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

Page 15: Js in the open

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

Page 16: Js in the open

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

Page 17: Js in the open

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

Page 18: Js in the open

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

Page 19: Js in the open

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

Page 20: Js in the open

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

Page 21: Js in the open

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

Page 22: Js in the open

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

Page 23: Js in the open

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

Page 24: Js in the open

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

Page 25: Js in the open

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

Page 26: Js in the open

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

Page 27: Js in the open

destructuring assignment

new in JavaScript 1.7

var a = 1;var b = 3; [a, b] = [b, a];

Friday, November 9, 12

Page 28: Js in the open

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

Page 29: Js in the open

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

Page 30: Js in the open

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

Page 31: Js in the open

2008

expression closures

getters and setters

generator expressions

more Array extras

new in JavaScript 1.8

Friday, November 9, 12

Page 32: Js in the open

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

Page 33: Js in the open

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

Page 34: Js in the open

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

Page 35: Js in the open

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

Page 36: Js in the open

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

Page 37: Js in the open

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

Page 38: Js in the open

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

Page 39: Js in the open

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

Page 40: Js in the open

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

Page 41: Js in the open

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

Page 42: Js in the open

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

Page 43: Js in the open

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

Page 44: Js in the open

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

Page 45: Js in the open

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

Page 46: Js in the open

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

Page 47: Js in the open

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

Page 48: Js in the open

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

Page 49: Js in the open

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

Page 50: Js in the open

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

Page 51: Js in the open

Rhino Unicorn

https://brendaneich.com/

Friday, November 9, 12

Page 52: Js in the open

https://brendaneich.com/

Friday, November 9, 12

Page 53: Js in the open

https://brendaneich.com/

Friday, November 9, 12

Page 54: Js in the open

Design patterns

Friday, November 9, 12

Page 55: Js in the open

We won’t talk about design patters

Friday, November 9, 12

Page 56: Js in the open

avoid defensive programming

premature optimization is evil

over-complicating things is eviler

over-engineering is the evilest

Friday, November 9, 12

Page 57: Js in the open

Friday, November 9, 12

Page 58: Js in the open

What we use at Mozilla

Friday, November 9, 12

Page 59: Js in the open

What we use at Mozilla

and you should too

Friday, November 9, 12

Page 60: Js in the open

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

Page 61: Js in the open

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

Page 62: Js in the open

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

Page 63: Js in the open

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

Page 64: Js in the open

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

Page 65: Js in the open

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

Page 66: Js in the open

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

Page 67: Js in the open

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

Page 68: Js in the open

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

Page 69: Js in the open

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

Page 70: Js in the open

// 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

Page 71: Js in the open

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

Page 72: Js in the open

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

Page 74: Js in the open

Debugging JavaScript in Firefox

(demo)

Friday, November 9, 12