Upgrade to Pro — share decks privately, control downloads, hide ads and more …

O fantástico mundo do JavaScript

O fantástico mundo do JavaScript

Apresentada no Brazil JS de 2013.

Você sabe os paradigmas e modelos que temos em mãos? O que mesmo é Javascript, sua razão de ser?

A saga de descobrimento de uma linguagem, suas características, dos objetos até módulos. E além disto, um pouco daquilo que está por vir com as novas especificações.

Jean Carlo Emer

August 23, 2013
Tweet

More Decks by Jean Carlo Emer

Other Decks in Programming

Transcript

  1. O fantástico mundo
    BrazilJS 2013
    do JavaScript

    View Slide

  2. Buenas
    !

    View Slide

  3. Brendan Eich
    criador do JS

    View Slide

  4. Jean Carlo Emer
    [
    'github',
    'speakerdeck',
    'twitter'
    ].map(service =>
    service + '.com/jcemer';
    );
    artesão da internet

    View Slide

  5. View Slide

  6. View Slide

  7. fantástico
    JavaScript é
    ?

    View Slide

  8. mil pessoas
    21% do GitHub
    ubíqua

    View Slide

  9. Sobre a palestra
    • Paradigmas
    • Organização de código
    • Modularização
    • Novas funcionalidades da ES6

    View Slide

  10. paradigmas
    !
    /Appl
    lement||window.HTM
    return!0;var a=document.createEl
    gment:"]*>([\\S\\s]*?)",
    i&&(Prototype.BrowserFeatures.SpecificElementExtensions=!1);v
    =null,c=
    n(c[0])&&(a=c.shift()),Object.extend(d,Class.Methods),d.superclass=a,d.subclasses=[],a&&
    );for(var e=0,f=c.length;f>e;e++)d.addMethods(c[e]);return d.prototype.initialize||(d.prototype.i
    s.superclass&&this.superclass.prototype,d=Object.keys(b);a&&(b.toString!=Object.prototype.toStri
    Of&&d.push("valueOf"));for(var e=0,f=d.length;f>e;e++){var g=d[e],h=b[g];if(c&&Object.isFunction
    apply(this,arguments)}}(g).wrap(i),h.valueOf=function(a){return function(){return a.valueOf.call(
    }this.prototype[g]=h}return this}var a=function(){for(var a in{toString:1})if("toString"===a)retu
    {switch(a){case null:return c;case void 0:return d}var b=typeof a;switch(b){case"boolean":return
    c]=b[c];return a}function t(a){try{return K(a)?"undefined":null===a?"null":a.inspect?a.inspect()
    ",{"":a},[])}function v(b,c,d){var e=c[b];r(e)===h&&"function"==typeof e.toJSON&&(e=e.toJSON(b));
    rn"null";case!0:return"true";case!1:return"false"}var g=typeof e;switch(g){case"string":return e.
    ect":for(var i=0,n=d.length;n>i;i++)if(d[i]===e)throw new TypeError("Cyclic reference to '"+e+"'
    ar p=v(i,e,d);o.push("undefined"==typeof p?"null":p)}o="["+o.join(",")+"]"}else{for(var q=Object
    ct(!0)+":"+p)}o="{"+o.join(",")+"}"}return d.pop(),o}}function w(a){return JSON.stringify(a)}func
    ing.interpret(a)}function z(a){if(r(a)!==h)throw new TypeError;var c=[];for(var d in a)b.call(a,
    eturn c}function A(a){var b=[];for(var c in a)b.push(a[c]);return b}function B(a){return s({},a)
    ){return a instanceof Hash}function G(b){return a.call(b)===i}function H(b){return a.call(b)===l}
    ){return"undefined"==typeof a}var
    ,b=Object.prototype.hasOwnProperty,c="Null",d="Undefined",e="Boolean",f="Number",g="String",h="O
    ",m="[object Array]",n="[object Date]",o=window.JSON&&"function"==typeof JSON.stringify&&"0"===J
    ,p=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable"
    !1;return!0}(),E="function"==typeof Array.isArray&&Array.isArray([])&&!Array.isArray({});E&&(D=Ar
    ,keys:Object.keys||z,values:A,clone:B,isElement:C,isArray:D,isHash:F,isFunction:G,isString:H,isN
    ototype,function(){function b(a,b){for(var c=a.length,d=b.length;d--;)a[c+d]=b[d];return a}funct
    s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g,"").replace(/\
    t.isUndefined(arguments[0]))return this;if(!Object.isFunction(this))throw new TypeError("The obj
    1),g=function(){var a=c(f,arguments),d=b,d=this instanceof g?this:b;return e.apply(d,a)};return
    return function(a){var f=b([a||window.event],e);return d.apply(c,f)}}function g(){if(!arguments.l
    s);return b.apply(this,a)}}function h(b){var c=this,d=a.call(arguments,1);return b=1e3*b,window.s
    is.delay.apply(this,a)}function j(a){var c=this;return function(){var d=b([c.bind(this)],argumen
    is._methodized;var a=this;return this._methodized=function(){var c=b([this],arguments);return a.
    umentNames:d,bindAsEventListener:f,curry:g,delay:h,defer:i,wrap:j,methodize:k};return Function.p
    s.getUTCMonth()
    getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString
    ISOString()}a.toISOString||(a.toISOString=b),a.toJSON|
    +?^=!:${}()|[\]\/\\])/g,"\\$1")};var Per
    terCallback:function(){th
    .timer),this

    View Slide

  11. • Orientação a objetos
    (através de prototype)
    • Funcional
    • Imperativo
    =[],a
    ubclasses.push(d));
    d.prototype.initialize||
    (d.prototype.initialize=
    {var c=this.superclass&&
    =Object.prototype.toStrin
    =Object.prototype.valueOf
    g=d[e],h=b[g];if(c&&Objec
    i=h;h=function(a){return
    (g).wrap(i),h.valueOf=func
    (i),h.toString=function(a)
    this.prototype[g]=h}return
    1})if("toString"===a)return
    function(){function r(a){sw
    a;switch(b){case"boolean":r
    function s(a,b){for(var c i
    K(a)?"undefined":null===a?"n
    RangeError)return"...";throw
    e=c[b];r(e)===h&&"function"=
    k:case j:case l:e=e.valueOf(
    1:return"false"}var g=typeof
    0);case"number":return isFini
    ++)if(d[i]===e)throw new Type
    o=[];if(f===m){for(var i=0,n=e
    p?"null":p)}o="["+o.join(",")+
    b=q[i],p=v(b,e,d);"undefined"!
    return d.pop(),o}}function w(a
    $H(a).toQueryString()}function
    function z(a){if(r(a)!==h)throw
    a)b.call(a,d)&&c.push(d);if(q)f
    A(a){var b=[];for(var c in a)b.
    {return!(!a||1!=a.nodeType)}func
    instanceof Hash}function G(b){re
    function I(b){return a.call(b)==
    {return"undefined"==typeof a}var
    a=Object.prototype.toString,b=Obj
    an",f="Number",g="String",h="Obj
    Number]",l="[objec
    Date]

    View Slide

  12. Valores são objetos!
    'BrazilJS'.toUpperCase();
    // BRAZILJS
    [1, 2, 3].slice(0, 2);
    // [1, 2]
    2013.08.toFixed();
    // '2013'
    (function (a, b) { return b }).call(null, 1, 2);
    // 2
    ({property: 'value'}).hasOwnProperty('property');
    // true

    View Slide

  13. • First-class functions
    Funções são como qualquer outro
    valor da linguagem
    var fn = function () { return 42 };
    var object = {
    ! method: function () {
    ! ! return "content"
    ! }
    };
    Funções

    View Slide

  14. • Higher-order functions
    Funções como argumentos ou
    valores de retorno
    var fn = function () { /* ... */ };
    document.addEventListener('click', fn);
    !function () {
    ! return function () { /* ... */ };
    }();

    View Slide

  15. É muito afude* ter objetos e
    funções de primeira classe
    !
    * afude: legal

    View Slide

  16. /Appl
    lement||window.HTM
    return!0;var a=document.createEl
    gment:"]*>([\\S\\s]*?)",
    i&&(Prototype.BrowserFeatures.SpecificElementExtensions=!1);v
    =null,c=
    n(c[0])&&(a=c.shift()),Object.extend(d,Class.Methods),d.superclass=a,d.subclasses=[],a&&
    );for(var e=0,f=c.length;f>e;e++)d.addMethods(c[e]);return d.prototype.initialize||(d.prototype.i
    s.superclass&&this.superclass.prototype,d=Object.keys(b);a&&(b.toString!=Object.prototype.toStri
    Of&&d.push("valueOf"));for(var e=0,f=d.length;f>e;e++){var g=d[e],h=b[g];if(c&&Object.isFunction
    apply(this,arguments)}}(g).wrap(i),h.valueOf=function(a){return function(){return a.valueOf.call(
    }this.prototype[g]=h}return this}var a=function(){for(var a in{toString:1})if("toString"===a)retu
    {switch(a){case null:return c;case void 0:return d}var b=typeof a;switch(b){case"boolean":return
    c]=b[c];return a}function t(a){try{return K(a)?"undefined":null===a?"null":a.inspect?a.inspect()
    ",{"":a},[])}function v(b,c,d){var e=c[b];r(e)===h&&"function"==typeof e.toJSON&&(e=e.toJSON(b));
    rn"null";case!0:return"true";case!1:return"false"}var g=typeof e;switch(g){case"string":return e.
    ect":for(var i=0,n=d.length;n>i;i++)if(d[i]===e)throw new TypeError("Cyclic reference to '"+e+"'
    ar p=v(i,e,d);o.push("undefined"==typeof p?"null":p)}o="["+o.join(",")+"]"}else{for(var q=Object
    ct(!0)+":"+p)}o="{"+o.join(",")+"}"}return d.pop(),o}}function w(a){return JSON.stringify(a)}func
    ing.interpret(a)}function z(a){if(r(a)!==h)throw new TypeError;var c=[];for(var d in a)b.call(a,
    eturn c}function A(a){var b=[];for(var c in a)b.push(a[c]);return b}function B(a){return s({},a)
    ){return a instanceof Hash}function G(b){return a.call(b)===i}function H(b){return a.call(b)===l}
    ){return"undefined"==typeof a}var
    ,b=Object.prototype.hasOwnProperty,c="Null",d="Undefined",e="Boolean",f="Number",g="String",h="O
    ",m="[object Array]",n="[object Date]",o=window.JSON&&"function"==typeof JSON.stringify&&"0"===J
    ,p=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable"
    !1;return!0}(),E="function"==typeof Array.isArray&&Array.isArray([])&&!Array.isArray({});E&&(D=Ar
    ,keys:Object.keys||z,values:A,clone:B,isElement:C,isArray:D,isHash:F,isFunction:G,isString:H,isN
    ototype,function(){function b(a,b){for(var c=a.length,d=b.length;d--;)a[c+d]=b[d];return a}funct
    s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g,"").replace(/\
    t.isUndefined(arguments[0]))return this;if(!Object.isFunction(this))throw new TypeError("The obj
    1),g=function(){var a=c(f,arguments),d=b,d=this instanceof g?this:b;return e.apply(d,a)};return
    return function(a){var f=b([a||window.event],e);return d.apply(c,f)}}function g(){if(!arguments.l
    s);return b.apply(this,a)}}function h(b){var c=this,d=a.call(arguments,1);return b=1e3*b,window.s
    is.delay.apply(this,a)}function j(a){var c=this;return function(){var d=b([c.bind(this)],argumen
    is._methodized;var a=this;return this._methodized=function(){var c=b([this],arguments);return a.
    umentNames:d,bindAsEventListener:f,curry:g,delay:h,defer:i,wrap:j,methodize:k};return Function.p
    s.getUTCMonth()
    getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString
    ISOString()}a.toISOString||(a.toISOString=b),a.toJSON|
    +?^=!:${}()|[\]\/\\])/g,"\\$1")};var Per
    terCallback:function(){th
    .timer),this
    objetos
    {}
    orientação a

    View Slide

  17. Tipos primitivos
    'BrazilJS';
    true;
    2013.08;
    The Secret Life of JavaScript Primitives
    http:/
    /javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-
    javascript-primitives
    undefined;
    null;
    new String('BrazilJS');
    new Number(2013.08);
    new Boolean(true);

    View Slide

  18. Quase tudo é objeto ou pode ser
    convertido para automaticamente
    !

    View Slide

  19. new String('BrazilJS').toUpperCase();
    new Array(1, 2, 3).slice(0, 2);
    new Number(2013.08).toFixed();
    new Function('a', 'b', 'return b').call(null, 1, 2);
    String.prototype.toUpperCase;
    Array.prototype.slice;
    Number.prototype.toFixed;
    Function.prototype.call;
    Construtores nativos

    View Slide

  20. • Prefira notaçõs literais quando
    disponíveis. Nestes, esqueça o new
    'BrazilJS'; [1, 2, 3]; 2013.08;
    (function (a, b) { return b })(1, 2);
    • Não adicione propriedades ao
    prototype destes construtores
    Maintainable JavaScript: Don’t modify objects you don’t own
    http:/
    /www.nczonline.net/blog/2010/03/02/maintainable-javascript-
    dont-modify-objects-you-down-own

    View Slide

  21. Object.prototype.var = 'foo';
    for (var prop in {}) {
    ! console.log(i, {}[prop]);
    }
    // log: var foo
    • A especificação pode evoluir e
    definir algum método que você já
    tenha declarado
    Avisei, não mexa!

    View Slide

  22. Object
    String
    'BrazilJS'
    { current: 0 }
    Array
    [1, 2, 3]
    ?
    ...

    View Slide

  23. Criando construtores
    function Counter() {
    this.current = 0;
    }
    var sample = new Counter();
    sample.current;
    // 0
    sample.constructor;
    // function Counter() {
    // this.current = 0
    // }

    View Slide

  24. function Counter(min, max, current) {
    this.min = min || 0;
    this.max = max || 10e9;
    this.current = current || this.min;
    }
    Counter.prototype.next = function() {
    return this.current =
    Math.min(this.max, this.current + 1);
    };
    Counter.prototype.isFirst = function() {
    return this.current <= this.min;
    };

    View Slide

  25. var sample = new Counter(0, 10);
    sample.isFirst();
    // true
    sample.next();
    // 1
    sample.isFirst();
    // false
    function Counter(min, max, current) {
    this.min = min || 0
    this.max = max || 10e9
    this.current = current || this.min
    }
    Counter.prototype.next = function() {
    return this.current =
    Math.min(this.max, this.current +
    }
    Counter.prototype.isFirst = function() {
    return this.current <= this.min
    }

    View Slide

  26. Especializando
    alert(sample);
    [object Object]
    sample = new Counter(0, 10);
    sample.toString = function() {
    return this.current.toString();
    };
    alert(sample);
    0
    melhor retornar uma string
    thanks @fnando

    View Slide

  27. delete sample.toString;
    Counter.prototype.toString = function() {
    return this.current + ' yeah';
    };
    alert(sample);
    0 yeah

    View Slide

  28. Nosso primeiro construtor: função
    prototype, e new
    !

    View Slide

  29. S.O.L.I.D.
    • Single responsability principle
    • Open/closed principle
    Após implementado, o construtor
    não deve mais ser modificado.
    Um novo construtor deve ser
    criado reusando código através de
    herança

    View Slide

  30. Herança?!
    Deixa disto!
    O que você precisa mesmo é de
    composição

    View Slide

  31. 1 ~ Composição
    function Counter(min, max, current) {
    /* ... */
    }
    function Spinner() {
    /* ... */
    }
    function Carousel(itens) {
    this.counter = new Counter(0, itens.length)
    this.loading = new Spinner()
    }

    View Slide

  32. E se eu precisar de um construtor
    igual ao Counter mas com goToLast
    ?

    View Slide

  33. O fantástico mundo
    do CoffeeScript
    ->

    View Slide

  34. class Counter
    constructor: (@min = 0, @max = 10e9, @current) ->
    @current ?= @min
    next: ->
    @current = Math.min(@max, @current + 1)
    isFirst: ->
    @current <= @min
    class CounterPlus extends Counter
    goToLast: ->
    @current = @max
    CoffeeScript

    View Slide

  35. sample = new CounterPlus(0, 10)
    CoffeeScript
    sample.goToLast()
    # 10
    sample.current
    # 10
    class Counter
    constructor: (@min = 0, @max = 10e9, @cur
    @current ?= @min
    next: ->
    @current = Math.min(@max, @current + 1)
    isFirst: ->
    @current <= @min
    class CounterPlus extends Counter
    goToLast: ->
    @current = @max

    View Slide

  36. class Counter
    constructor: (@min = 0, @max = 10e9, @current) ->
    @current ?= @min
    next: ->
    @current = Math.min(@max, @current + 1)
    isFirst: ->
    @current <= @min
    class CounterPlus extends Counter
    goToLast: ->
    @current = @max
    CoffeeScript

    View Slide

  37. ES6 classes
    class Counter {
    constructor(min = 0, max = 10e9, current = min) {}
    next() {
    return this.current =
    Math.min(this.max, this.current + 1)
    }
    isFirst() {
    return this.current <= this.min
    }
    }
    class CounterPlus extends Counter {
    goToLast() {
    this.current = this.max
    }
    }

    View Slide

  38. function Counter(min, max, current) {
    this.min = min || 0
    this.max = max || 10e9
    this.current = current || this.min
    }
    Counter.prototype.next = function() {
    return this.current =
    Math.min(this.max, this.current + 1)
    }
    Counter.prototype.isFirst = function() {
    return this.current <= this.min
    }
    class CounterPlus extends Counter {
    goToLast() {
    this.current = this.max
    }

    View Slide

  39. function CounterPlus() {
    Counter.apply(this, arguments)
    }
    function InheritCounter() {}
    InheritCounter.prototype = Counter.prototype
    CounterPlus.prototype = new InheritCounter()
    CounterPlus.prototype.constructor = CounterPlus
    CounterPlus.prototype.goToLast = function() {
    return this.current = this.max
    }
    class CounterPlus extends Counter {
    goToLast() {
    this.current = this.max
    }
    }
    function Counter(min, max, current) { /* ... */ }

    View Slide

  40. function CounterPlus() {
    Counter.apply(this, arguments)
    }
    function InheritCounter() {}
    InheritCounter.prototype = Counter.prototype
    CounterPlus.prototype = new InheritCounter()
    CounterPlus.prototype.constructor = CounterPlus
    CounterPlus.prototype.goToLast = function() {
    return this.current = this.max
    }
    function Counter(min, max, current) { /* ... */ }
    class CounterPlus extends Counter {
    goToLast() {
    this.current = this.max
    }
    }

    View Slide

  41. function CounterPlus() {
    Counter.apply(this, arguments)
    }
    function InheritCounter() {}
    InheritCounter.prototype = Counter.prototype
    CounterPlus.prototype = new InheritCounter()
    CounterPlus.prototype.constructor = CounterPlus
    CounterPlus.prototype.goToLast = function() {
    return this.current = this.max
    }
    function Counter(min, max, current) { /* ... */ }
    class CounterPlus extends Counter {
    goToLast() {
    this.current = this.max
    }
    }

    View Slide

  42. function Counter(min, max, current) { /* ... */ }
    function CounterPlus() {
    Counter.apply(this, arguments)
    }
    function InheritCounter() {}
    InheritCounter.prototype = Counter.prototype
    CounterPlus.prototype = new InheritCounter()
    CounterPlus.prototype.constructor = CounterPlus
    CounterPlus.prototype.goToLast = function() {
    return this.current = this.max
    }
    2 ~ Herança

    View Slide

  43. ES6 classes
    class Counter { /* ... */ }
    class CounterPlus extends Counter {
    goToLast() {
    this.current = this.max
    }
    }

    View Slide

  44. ES6 Class ~ Transpilers
    Comece a usar as classes do ES6 agora
    mesmo... em qualquer browser!
    Harmonizr
    https:/
    /github.com/jdiamond/harmonizr
    ES6-Transpiler.js
    https:/
    /github.com/termi/es6-transpiler
    Traceur Compiler
    https:/
    /github.com/google/traceur-compiler

    View Slide

  45. 3 ~ Mixin
    var validateMixin = {
    ! validate: function () { /* ... */ }
    }
    var eventsMixin = {
    ! subscribe: function () { /* ... */ },
    ! publish: function () { /* ... */ }
    }
    function Model() {
    ! /* ... */
    }
    $.extend(Model.prototype, validateMixin,
    eventsMixin)

    View Slide

  46. Recapitulando técnicas
    • Composição
    Contendo outros construtores que
    implementam funcionalidades
    • Herança
    Via cadeia de prototype
    • Mixin
    Estendendo o prototype

    View Slide

  47. S.O.L.I.D.
    Open/closed principle
    Após implementado, o construtor
    não deve mais ser modificado.
    Um novo construtor deve ser
    criado reusando código através de
    herança
    The S.O.L.I.D. Object Oriented Programming(OOP) Principles
    http:/
    /www.codeproject.com/Articles/60845/The-S-O-L-I-D-Object-
    Oriented-Programming-OOP-Prin

    View Slide

  48. /Appl
    lement||window.HTM
    return!0;var a=document.createEl
    gment:"]*>([\\S\\s]*?)",
    i&&(Prototype.BrowserFeatures.SpecificElementExtensions=!1);v
    =null,c=
    n(c[0])&&(a=c.shift()),Object.extend(d,Class.Methods),d.superclass=a,d.subclasses=[],a&&
    );for(var e=0,f=c.length;f>e;e++)d.addMethods(c[e]);return d.prototype.initialize||(d.prototype.i
    s.superclass&&this.superclass.prototype,d=Object.keys(b);a&&(b.toString!=Object.prototype.toStri
    Of&&d.push("valueOf"));for(var e=0,f=d.length;f>e;e++){var g=d[e],h=b[g];if(c&&Object.isFunction
    apply(this,arguments)}}(g).wrap(i),h.valueOf=function(a){return function(){return a.valueOf.call(
    }this.prototype[g]=h}return this}var a=function(){for(var a in{toString:1})if("toString"===a)retu
    {switch(a){case null:return c;case void 0:return d}var b=typeof a;switch(b){case"boolean":return
    c]=b[c];return a}function t(a){try{return K(a)?"undefined":null===a?"null":a.inspect?a.inspect()
    ",{"":a},[])}function v(b,c,d){var e=c[b];r(e)===h&&"function"==typeof e.toJSON&&(e=e.toJSON(b));
    rn"null";case!0:return"true";case!1:return"false"}var g=typeof e;switch(g){case"string":return e.
    ect":for(var i=0,n=d.length;n>i;i++)if(d[i]===e)throw new TypeError("Cyclic reference to '"+e+"'
    ar p=v(i,e,d);o.push("undefined"==typeof p?"null":p)}o="["+o.join(",")+"]"}else{for(var q=Object
    ct(!0)+":"+p)}o="{"+o.join(",")+"}"}return d.pop(),o}}function w(a){return JSON.stringify(a)}func
    ing.interpret(a)}function z(a){if(r(a)!==h)throw new TypeError;var c=[];for(var d in a)b.call(a,
    eturn c}function A(a){var b=[];for(var c in a)b.push(a[c]);return b}function B(a){return s({},a)
    ){return a instanceof Hash}function G(b){return a.call(b)===i}function H(b){return a.call(b)===l}
    ){return"undefined"==typeof a}var
    ,b=Object.prototype.hasOwnProperty,c="Null",d="Undefined",e="Boolean",f="Number",g="String",h="O
    ",m="[object Array]",n="[object Date]",o=window.JSON&&"function"==typeof JSON.stringify&&"0"===J
    ,p=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable"
    !1;return!0}(),E="function"==typeof Array.isArray&&Array.isArray([])&&!Array.isArray({});E&&(D=Ar
    ,keys:Object.keys||z,values:A,clone:B,isElement:C,isArray:D,isHash:F,isFunction:G,isString:H,isN
    ototype,function(){function b(a,b){for(var c=a.length,d=b.length;d--;)a[c+d]=b[d];return a}funct
    s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g,"").replace(/\
    t.isUndefined(arguments[0]))return this;if(!Object.isFunction(this))throw new TypeError("The obj
    1),g=function(){var a=c(f,arguments),d=b,d=this instanceof g?this:b;return e.apply(d,a)};return
    return function(a){var f=b([a||window.event],e);return d.apply(c,f)}}function g(){if(!arguments.l
    s);return b.apply(this,a)}}function h(b){var c=this,d=a.call(arguments,1);return b=1e3*b,window.s
    is.delay.apply(this,a)}function j(a){var c=this;return function(){var d=b([c.bind(this)],argumen
    is._methodized;var a=this;return this._methodized=function(){var c=b([this],arguments);return a.
    umentNames:d,bindAsEventListener:f,curry:g,delay:h,defer:i,wrap:j,methodize:k};return Function.p
    s.getUTCMonth()
    getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString
    ISOString()}a.toISOString||(a.toISOString=b),a.toJSON|
    +?^=!:${}()|[\]\/\\])/g,"\\$1")};var Per
    terCallback:function(){th
    .timer),this
    new Counter()
    VS
    { current: 0 }

    View Slide

  49. • Objetos literais não possibilitam o
    uso de herança, apenas
    composição e mixin
    • Objetos literais não compartilham
    código através do prototype

    View Slide

  50. • Objetos gerados por construtores
    podem ser mais rápidos ao
    acessar propriedades
    Teste no jsPerf
    http:/
    /jsperf.com/property-access-object-literal-vs-constructor/3
    V8: Fast property Access
    https:/
    /developers.google.com/v8/design#prop_access
    via @askoth

    View Slide

  51. É poderoso: funções construtoras,
    new, call e de bônus o prototype
    !

    View Slide

  52. ]*>([\\
    serFeatures.SpecificE
    ft()),Object.extend(d,Class.Methods),d.superclass
    =0,f=c.length;f>e;e++)d.addMethods(c[e]);return d.prototype.ini
    =this.superclass&&this.superclass.prototype,d=Object.keys(b);a&&(b.toString!=O
    t.prototype.valueOf&&d.push("valueOf"));for(var e=0,f=d.length;f>e;e++){var g=d[e],h=b[g];i
    unction(){return c[a].apply(this,arguments)}}(g).wrap(i),h.valueOf=function(a){return function()
    .toString.call(a)}}(i)}this.prototype[g]=h}return this}var a=function(){for(var a in{toString:1}
    unction(){function r(a){switch(a){case null:return c;case void 0:return d}var b=typeof a;switch(b
    a,b){for(var c in b)a[c]=b[c];return a}function t(a){try{return K(a)?"undefined":null===a?"null"
    nction u(a){return v("",{"":a},[])}function v(b,c,d){var e=c[b];r(e)===h&&"function"==typeof e.t
    itch(e){case null:return"null";case!0:return"true";case!1:return"false"}var g=typeof e;switch(g){
    ring(e):"null";case"object":for(var i=0,n=d.length;n>i;i++)if(d[i]===e)throw new TypeError("Cycli
    ,n=e.length;n>i;i++){var p=v(i,e,d);o.push("undefined"==typeof p?"null":p)}o="["+o.join(",")+"]"
    peof p&&o.push(b.inspect(!0)+":"+p)}o="{"+o.join(",")+"}"}return d.pop(),o}}function w(a){return
    a.toHTML?a.toHTML():String.interpret(a)}function z(a){if(r(a)!==h)throw new TypeError;var c=[];fo
    .call(a,d)&&c.push(d);return c}function A(a){var b=[];for(var c in a)b.push(a[c]);return b}functi
    ll(b)===m}function F(a){return a instanceof Hash}function G(b){return a.call(b)===i}function H(b
    ll(b)===n}function K(a){return"undefined"==typeof a}var
    ject.prototype.toString,b=Object.prototype.hasOwnProperty,c="Null",d="Undefined",e="Boolean",f="N
    r]",l="[object String]",m="[object Array]",n="[object Date]",o=window.JSON&&"function"==typeof J
    stringify(Prototype.K),p=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf"
    ("toString"===a)return!1;return!0}(),E="function"==typeof Array.isArray&&Array.isArray([])&&!Arra
    oQueryString:x,toHTML:y,keys:Object.keys||z,values:A,clone:B,isElement:C,isArray:D,isHash:F,isFun
    ect.extend(Function.prototype,function(){function b(a,b){for(var c=a.length,d=b.length;d--;)a[c+
    .toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])
    guments.length<2&&Object.isUndefined(arguments[0]))return this;if(!Object.isFunction(this))throw
    his,f=a.call(arguments,1),g=function(){var a=c(f,arguments),d=b,d=this instanceof g?this:b;return
    e=a.call(arguments,1);return function(a){var f=b([a||window.event],e);return d.apply(c,f)}}funct
    n(){var a=c(d,arguments);return b.apply(this,a)}}function h(b){var c=this,d=a.call(arguments,1);
    1],arguments);return this.delay.apply(this,a)}function j(a){var c=this;return function(){var d=b(
    ._methodized)return this._methodized;var a=this;return this._methodized=function(){var c=b([this
    prototype.slice,l={argumentNames:d,bindAsEventListener:f,curry:g,delay:h,defer:i,wrap:j,methodiz
    UTCFullYear()+"-"+(this.getUTCMonth()
    ddedString(2)+"-"+this.getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString(2)+":
    ion c(){return this.toISOString()}a.toISOString||(a.toISOString=b),a.toJSON||(a.toJSON=c)}(Da
    tring(a).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")};var PeriodicalExecuter=C
    gisterCallback()},registerCallback:function(){this.timer=setInterv
    er&&(clearInterval(this.timer),this.timer=null)},onT
    hrow this.currentlyExecuting=!1,a}}})
    \\\\"}}),Object.extend(
    sub(a,b){
    funcional
    ->

    View Slide

  53. Coleções
    var data = [1, 2, 3, 4, 5, 6]
    , result = []
    , i = 0
    , item = null
    while (i < data.length) {
    item = data[i]
    result.push(item * 2)
    i++
    }
    // result = [2, 4, 6, 8, 10, 12]

    View Slide

  54. Arrays extras
    • Métodos para manipular arrays
    vindos da especificação do ES5

    View Slide

  55. var data = [1, 2, 3, 4, 5, 6]
    , result
    result = data.map(function (item) {
    return item * 2
    })
    // result = [2, 4, 6, 8, 10, 12]
    // data = [1, 2, 3, 4, 5, 6]

    View Slide

  56. var data = [1, 2, 3, 4, 5, 6]
    , result
    result = data.reduce(function (sum, item) {
    return sum + item
    }, 0)
    // TRACE:
    // 0 + 1
    // (0 + 1) + 2
    // (0 + 1 + 2) + 3
    // (0 + 1 + 2 + 3) + 4
    // (0 + 1 + 2 + 3 + 4) + 5
    // (0 + 1 + 2 + 3 + 4 + 5) + 6
    // result = 21
    // data = [1, 2, 3, 4, 5, 6]

    View Slide

  57. Manipulando arrays
    Array.prototype.forEach
    Array.prototype.every
    Array.prototype.some
    Array.prototype.filter
    Array.prototype.map
    Array.prototype.reduce
    Array.prototype.reduceRight
    Implementado em ie9+
    http:/
    /kangax.github.io/es5-compat-table
    ES5-shim
    https:/
    /github.com/kriskowal/es5-shim

    View Slide

  58. Bibliotecas funcionais
    • O JavaScript não possui muitas
    funções para uso geral
    • Apenas arrays podem ser
    manipulados por funções como se
    fossem coleções

    View Slide

  59. jQuery
    var data = { what: 'BrazilJS', where: 'POA' }
    $.map(data, function (item) {
    return item
    })
    // ['BrazilJS', 'POA']
    var data = { what: 'BrazilJS', where: 'POA' }
    $.each(data, function (item) {
    console.log(item)
    })
    // log: what
    // log: where

    View Slide

  60. Underscore
    _.map({ what: 'BrazilJS', city: 'POA' }, _.identity)
    // ['BrazilJS', 'POA']
    _.flatten([1, [2], [3, [[4]]]]);
    // [1, 2, 3, 4];
    _.groupBy([1.3, 2.1, 2.4], function (num) {
    return Math.floor(num)
    })
    // {1: [1.3], 2: [2.1, 2.4]}

    View Slide

  61. Bilby.js
    Modelagem Categorial do Programa Google Talk
    https:/
    /speakerdeck.com/jcemer/modelagem-categorial-do-programa-
    google-talk
    • Aplica Teoria das Categorias...

    View Slide

  62. Bilby.js
    Modelagem Categorial do Programa Google Talk
    https:/
    /speakerdeck.com/jcemer/modelagem-categorial-do-programa-
    google-talk
    • Aplica Teoria das Categorias...
    Functional JavaScript
    Michael Fogus
    http:/
    /shop.oreilly.com/product/0636920028857.do

    View Slide

  63. /Appl
    lement||window.HTM
    return!0;var a=document.createEl
    gment:"]*>([\\S\\s]*?)",
    i&&(Prototype.BrowserFeatures.SpecificElementExtensions=!1);v
    =null,c=
    n(c[0])&&(a=c.shift()),Object.extend(d,Class.Methods),d.superclass=a,d.subclasses=[],a&&
    );for(var e=0,f=c.length;f>e;e++)d.addMethods(c[e]);return d.prototype.initialize||(d.prototype.i
    s.superclass&&this.superclass.prototype,d=Object.keys(b);a&&(b.toString!=Object.prototype.toStri
    Of&&d.push("valueOf"));for(var e=0,f=d.length;f>e;e++){var g=d[e],h=b[g];if(c&&Object.isFunction
    apply(this,arguments)}}(g).wrap(i),h.valueOf=function(a){return function(){return a.valueOf.call(
    }this.prototype[g]=h}return this}var a=function(){for(var a in{toString:1})if("toString"===a)retu
    {switch(a){case null:return c;case void 0:return d}var b=typeof a;switch(b){case"boolean":return
    c]=b[c];return a}function t(a){try{return K(a)?"undefined":null===a?"null":a.inspect?a.inspect()
    ",{"":a},[])}function v(b,c,d){var e=c[b];r(e)===h&&"function"==typeof e.toJSON&&(e=e.toJSON(b));
    rn"null";case!0:return"true";case!1:return"false"}var g=typeof e;switch(g){case"string":return e.
    ect":for(var i=0,n=d.length;n>i;i++)if(d[i]===e)throw new TypeError("Cyclic reference to '"+e+"'
    ar p=v(i,e,d);o.push("undefined"==typeof p?"null":p)}o="["+o.join(",")+"]"}else{for(var q=Object
    ct(!0)+":"+p)}o="{"+o.join(",")+"}"}return d.pop(),o}}function w(a){return JSON.stringify(a)}func
    ing.interpret(a)}function z(a){if(r(a)!==h)throw new TypeError;var c=[];for(var d in a)b.call(a,
    eturn c}function A(a){var b=[];for(var c in a)b.push(a[c]);return b}function B(a){return s({},a)
    ){return a instanceof Hash}function G(b){return a.call(b)===i}function H(b){return a.call(b)===l}
    ){return"undefined"==typeof a}var
    ,b=Object.prototype.hasOwnProperty,c="Null",d="Undefined",e="Boolean",f="Number",g="String",h="O
    ",m="[object Array]",n="[object Date]",o=window.JSON&&"function"==typeof JSON.stringify&&"0"===J
    ,p=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable"
    !1;return!0}(),E="function"==typeof Array.isArray&&Array.isArray([])&&!Array.isArray({});E&&(D=Ar
    ,keys:Object.keys||z,values:A,clone:B,isElement:C,isArray:D,isHash:F,isFunction:G,isString:H,isN
    ototype,function(){function b(a,b){for(var c=a.length,d=b.length;d--;)a[c+d]=b[d];return a}funct
    s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g,"").replace(/\
    t.isUndefined(arguments[0]))return this;if(!Object.isFunction(this))throw new TypeError("The obj
    1),g=function(){var a=c(f,arguments),d=b,d=this instanceof g?this:b;return e.apply(d,a)};return
    return function(a){var f=b([a||window.event],e);return d.apply(c,f)}}function g(){if(!arguments.l
    s);return b.apply(this,a)}}function h(b){var c=this,d=a.call(arguments,1);return b=1e3*b,window.s
    is.delay.apply(this,a)}function j(a){var c=this;return function(){var d=b([c.bind(this)],argumen
    is._methodized;var a=this;return this._methodized=function(){var c=b([this],arguments);return a.
    umentNames:d,bindAsEventListener:f,curry:g,delay:h,defer:i,wrap:j,methodize:k};return Function.p
    s.getUTCMonth()
    getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString
    ISOString()}a.toISOString||(a.toISOString=b),a.toJSON|
    +?^=!:${}()|[\]\/\\])/g,"\\$1")};var Per
    terCallback:function(){th
    .timer),this
    VS
    orientação
    a objetos funcional

    View Slide

  64. Um paradigma não exclui o outro!
    • Orientação a objetos
    Comportamento e estado
    • Funcional
    Computação baseada em
    transformação dos dados

    View Slide

  65. Como mantenho informações
    privadas em meu código
    ?

    View Slide

  66. View Slide

  67. Eu não escondo com frequência.
    Mas quando o faço, usar closure é a
    única opção
    Michael Fogus

    View Slide

  68. Closure?!
    • Função que captura variáveis do
    escopo em que é definida
    var counter = (function(){
    var current = 0
    return function closure () {
    return current++
    }
    })()

    View Slide

  69. function counterClosure(min, max, current) {
    min = min || 0
    max = max || 10e9
    current = current || min
    return {
    next: function () {
    return current =
    Math.min(max, current + 1)
    },
    isFirst: function () {
    return current <= min
    }
    }
    }
    var counter = counterClosure()

    View Slide

  70. Ok, agora tenho meu código
    privado
    !

    View Slide

  71. [...], the browser remains an
    inherently insecure execution
    environment; no amount of
    JavaScript trickery can fix that. If you
    are writing client-side code that
    needs to be trusted, my advice is to
    off-load sensitive operations to a
    secure server.
    Information Hiding in JavaScript
    Mike Pennisi

    View Slide

  72. [...], o browser continua um
    ambiente de execução inseguro;
    artimanhas no JavaScript não
    podem corrigir isto. Se você está
    codando algo que precise ser
    confiável, meu aviso é que operações
    sensíveis devam ser reservadas a um
    servidor seguro.
    Information Hiding in JavaScript
    Mike Pennisi

    View Slide

  73. Closure Pattern
    The access protection provided by
    this closure pattern is a powerful
    technique available to JavaScript
    programmers for keeping sanity in
    the face of software complexity.
    Functional JavaScript
    Michael Fogus

    View Slide

  74. Closure Pattern
    A restrição de acesso proporcionada
    pelo closure pattern é uma técnica
    poderosa, que pode ajudar
    desenvolvedores JavaScript a manter
    o nível de complexidade do software
    sob controle.
    Functional JavaScript
    Michael Fogus

    View Slide

  75. >([\\
    erFeatures.Specific
    t()),Object.extend(d,Class.Methods),d.superclas
    ,f=c.length;f>e;e++)d.addMethods(c[e]);return d.prototype.ini
    his.superclass&&this.superclass.prototype,d=Object.keys(b);a&&(b.toString!=
    .prototype.valueOf&&d.push("valueOf"));for(var e=0,f=d.length;f>e;e++){var g=d[e],h=b[g];
    function(){return c[a].apply(this,arguments)}}(g).wrap(i),h.valueOf=function(a){return function()
    a.toString.call(a)}}(i)}this.prototype[g]=h}return this}var a=function(){for(var a in{toString:1}
    unction(){function r(a){switch(a){case null:return c;case void 0:return d}var b=typeof a;switch(
    (a,b){for(var c in b)a[c]=b[c];return a}function t(a){try{return K(a)?"undefined":null===a?"null
    unction u(a){return v("",{"":a},[])}function v(b,c,d){var e=c[b];r(e)===h&&"function"==typeof e.t
    witch(e){case null:return"null";case!0:return"true";case!1:return"false"}var g=typeof e;switch(g)
    ring(e):"null";case"object":for(var i=0,n=d.length;n>i;i++)if(d[i]===e)throw new TypeError("Cycl
    0,n=e.length;n>i;i++){var p=v(i,e,d);o.push("undefined"==typeof p?"null":p)}o="["+o.join(",")+"]
    ypeof p&&o.push(b.inspect(!0)+":"+p)}o="{"+o.join(",")+"}"}return d.pop(),o}}function w(a){return
    a.toHTML?a.toHTML():String.interpret(a)}function z(a){if(r(a)!==h)throw new TypeError;var c=[];f
    .call(a,d)&&c.push(d);return c}function A(a){var b=[];for(var c in a)b.push(a[c]);return b}funct
    all(b)===m}function F(a){return a instanceof Hash}function G(b){return a.call(b)===i}function H(b
    all(b)===n}function K(a){return"undefined"==typeof a}var
    ject.prototype.toString,b=Object.prototype.hasOwnProperty,c="Null",d="Undefined",e="Boolean",f="
    er]",l="[object String]",m="[object Array]",n="[object Date]",o=window.JSON&&"function"==typeof
    .stringify(Prototype.K),p=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf"
    f("toString"===a)return!1;return!0}(),E="function"==typeof Array.isArray&&Array.isArray([])&&!Arr
    oQueryString:x,toHTML:y,keys:Object.keys||z,values:A,clone:B,isElement:C,isArray:D,isHash:F,isFu
    ject.extend(Function.prototype,function(){function b(a,b){for(var c=a.length,d=b.length;d--;)a[c
    s.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1].replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])
    guments.length<2&&Object.isUndefined(arguments[0]))return this;if(!Object.isFunction(this))throw
    his,f=a.call(arguments,1),g=function(){var a=c(f,arguments),d=b,d=this instanceof g?this:b;retur
    ,e=a.call(arguments,1);return function(a){var f=b([a||window.event],e);return d.apply(c,f)}}func
    on(){var a=c(d,arguments);return b.apply(this,a)}}function h(b){var c=this,d=a.call(arguments,1);
    1],arguments);return this.delay.apply(this,a)}function j(a){var c=this;return function(){var d=b
    s._methodized)return this._methodized;var a=this;return this._methodized=function(){var c=b([thi
    .prototype.slice,l={argumentNames:d,bindAsEventListener:f,curry:g,delay:h,defer:i,wrap:j,methodiz
    tUTCFullYear()+"-"+(this.getUTCMonth()
    ddedString(2)+"-"+this.getUTCDate().toPaddedString(2)+"T"+this.getUTCHours().toPaddedString(2)+"
    tion c(){return this.toISOString()}a.toISOString||(a.toISOString=b),a.toJSON||(a.toJSON=c)}(Date
    String(a).replace(/([.*+?^=!:${}()|[\]\/\\])/g,"\\$1")};var PeriodicalExecuter=Cla
    gisterCallback()},registerCallback:function(){this.timer=setInterva
    er&&(clearInterval(this.timer),this.timer=null)},onTi
    throw this.currentlyExecuting=!1,a}}});
    "\\\\"}}),Object.extend(St
    sub(a,b){va
    módulos
    ( )

    View Slide

  76. • Peças isoladas que podem ser
    adicionadas e removidas quando
    necessário
    • Devem poder indicar demais
    peças que constituem
    dependência

    View Slide

  77. Module Pattern via namespace
    var namespace = {}
    namespace.Util = (function () { /* ... */ })()
    namespace.Data = (function () {
    var util = namespace.Util
    , data = {}
    return {
    set: function (el, key, value) { /* ... */ }
    , get: function (el, key) { /* ... */}
    }
    })()

    View Slide

  78. Rye.define('Data', function () {
    var util = Rye.require('Util')
    , data = {}
    function set (element, key, value) { /* ... */ }
    function get (element, key) { /* ... */}
    return {
    set: set
    , get: get
    }
    })
    Rye Modules Revealing Module Pattern
    Rye
    http:/
    /ryejs.com

    View Slide

  79. AMD Asyncronous Module Definition
    define(['util'], function (util) {
    var data = {}
    function set (element, key, value) { /* ... */ }
    function get (element, key) { /* ... */}
    return {
    set: set
    , get: get
    }
    })

    View Slide

  80. AMD Asyncronous Module Definition
    Require.js
    http:/
    /requirejs.org
    AMD is better for the web than CommonJS modules
    http:/
    /blog.millermedeiros.com/amd-is-better-for-the-web-than-
    commonjs-modules
    • Assíncrono por natureza e
    funciona nos browsers atuais
    • Necessita de um loader como o
    require.js

    View Slide

  81. CJS CommonJS module
    var util = require('util')
    , data = {}
    function set (element, key, value) { /* ... */ }
    function get (element, key) { /* ... */}
    exports = {
    set: set
    , get: get
    }

    View Slide

  82. • Não compatível com browsers
    Pode ser levado ao browser através
    de ferramentas como browserify
    Browserify
    http:/
    /browserify.org
    Asynchronous Module Loading With Browserify
    http:/
    /esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-
    loading-with-browserify
    CJS CommonJS module

    View Slide

  83. ES6 modules

    View Slide

  84. ES6 Modules
    module util from "util"
    let data = {}
    export function set () { /* ... */ }
    export function get () { /* ... */ }
    Module Spec
    http:/
    /wiki.ecmascript.org/doku.php?id=harmony:modules
    Module loaders Spec
    http:/
    /wiki.ecmascript.org/doku.php?id=harmony:module_loaders
    ES6 modules

    View Slide

  85. ES6 Modules ~ Transpilers
    Comece a usar os módulos do ES6 agora
    mesmo... em qualquer browser!
    Harmonizr (desatualizado)
    https:/
    /github.com/jdiamond/harmonizr
    Esprima ~ ES6 parser
    https:/
    /github.com/ariya/esprima/tree/harmony
    ES6 Module Loader
    https:/
    /github.com/ModuleLoader/es6-module-loader
    ES6 modules

    View Slide

  86. JSPM module loader
    • Suporta ES6, AMD e CJS
    • Utiliza o protocolo SPDY
    JSPM
    http:/
    /jspm.io
    SPDY
    http:/
    /en.wikipedia.org/wiki/SPDY

    View Slide

  87. E muito mais...
    • let & const
    As novas vars
    • Set
    Bem vinda teoria dos conjuntos
    Spec da ES6
    http:/
    /wiki.ecmascript.org/doku.php?id=harmony:proposals
    ES6 Compatibility table
    http:/
    /kangax.github.io/es5-compat-table/es6
    ES6 stuffs

    View Slide

  88. E muito mais...
    • Iterators & Generators
    Evoluíndo o conceito de coleções e
    controlando fluxo do código
    ES6 stuffs
    Spec da ES6
    http:/
    /wiki.ecmascript.org/doku.php?id=harmony:proposals
    ES6 Compatibility table
    http:/
    /kangax.github.io/es5-compat-table/es6

    View Slide

  89. Perguntas
    ?
    @jcemer

    View Slide

  90. Setas, setas, setas, setas, setas!!!!
    Loop Infinito - ECMAScript 6 Arrow Function
    http:/
    /loopinfinito.com.br/2013/08/20/ecmascript-6-arrow-function
    Callable entities in ECMAScript 6
    http:/
    /www.2ality.com/2013/08/es6-callables.html
    ES6 arrows
    [
    'github',
    'speakerdeck',
    'twitter'
    ].map (service =>
    service + '.com/jcemer'
    )

    View Slide

  91. fantástico
    JavaScript é
    ?

    View Slide

  92. Obrigado
    !
    @jcemer

    View Slide