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
new in JavaScript 1.6
                                        2006



                               Functional collectors

                                    Array extras

                              Array and String generics

                                 for each..in loops




Friday, November 9, 12
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
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
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
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
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
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
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
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
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
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
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
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
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
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
new in JavaScript 1.7
                               destructuring assignment




            var a = 1;
            var b = 3;

            [a, b] = [b, a];




Friday, November 9, 12
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
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
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
new in JavaScript 1.8
                                      2008



                               expression closures

                               getters and setters

                              generator expressions

                               more Array extras




Friday, November 9, 12
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
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
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
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
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
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
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
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
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
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
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
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
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
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); // 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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

Js in the open

  • 1.
    JS in theopen (or JS in the wild) Friday, November 9, 12
  • 2.
    @victorporof Programmer at Mozilla Friday, November 9, 12
  • 3.
    The JavaScript youprobably know Friday, November 9, 12
  • 4.
    Number String Boolean Object (Function, Array, Date, RegExp ...) Function Null Undefined Friday, November 9, 12
  • 5.
    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
  • 6.
    new Number(3) new String(“Gangnam Style”) new Boolean(false) Friday, November 9, 12
  • 7.
    typeof new Number(3) == “object” typeof new String(“Gangnam Style”) == “object” typeof new Boolean(false) == “object” Friday, November 9, 12
  • 8.
    typeof new Number(3) == “object” typeof new String(“Gangnam Style”) == “object” typeof new Boolean(false) == “object” Constructors Friday, November 9, 12
  • 9.
    JavaScript is fundamentallyabout Objects Friday, November 9, 12
  • 10.
    The JavaScript youprobably don’t know Friday, November 9, 12
  • 11.
  • 12.
    new in JavaScript1.6 2006 Functional collectors Array extras Array and String generics for each..in loops Friday, November 9, 12
  • 13.
    new in JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.7 destructuring assignment var a = 1; var b = 3; [a, b] = [b, a]; Friday, November 9, 12
  • 28.
    new in JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.8 2008 expression closures getters and setters generator expressions more Array extras Friday, November 9, 12
  • 32.
    new in JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 JavaScript1.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 ES6and 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 restparams // 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. WeakMaps // 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
  • 52.
  • 53.
  • 54.
  • 55.
    We won’t talkabout 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
  • 57.
  • 58.
    What we useat Mozilla Friday, November 9, 12
  • 59.
    What we useat 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
  • 74.
    Debugging JavaScript inFirefox (demo) Friday, November 9, 12