Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

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. Sobre a palestra • Paradigmas • Organização de código •

    Modularização • Novas funcionalidades da ES6
  2. paradigmas ! /Appl lement||window.HTM return!0;var a=document.createEl gment:"<script[^>]*>([\\S\\s]*?)</script\\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
  3. • 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]
  4. 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
  5. • 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
  6. • Higher-order functions Funções como argumentos ou valores de retorno

    var fn = function () { /* ... */ }; document.addEventListener('click', fn); !function () { ! return function () { /* ... */ }; }();
  7. /Appl lement||window.HTM return!0;var a=document.createEl gment:"<script[^>]*>([\\S\\s]*?)</script\\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
  8. 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);
  9. 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
  10. • 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
  11. 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!
  12. Criando construtores function Counter() { this.current = 0; } var

    sample = new Counter(); sample.current; // 0 sample.constructor; // function Counter() { // this.current = 0 // }
  13. 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; };
  14. 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 }
  15. 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
  16. 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
  17. 1 ~ Composição function Counter(min, max, current) { /* ...

    */ } function Spinner() { /* ... */ } function Carousel(itens) { this.counter = new Counter(0, itens.length) this.loading = new Spinner() }
  18. 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
  19. 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
  20. 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
  21. 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 } }
  22. 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 }
  23. 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) { /* ... */ }
  24. 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 } }
  25. 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 } }
  26. 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
  27. ES6 classes class Counter { /* ... */ } class

    CounterPlus extends Counter { goToLast() { this.current = this.max } }
  28. 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
  29. 3 ~ Mixin var validateMixin = { ! validate: function

    () { /* ... */ } } var eventsMixin = { ! subscribe: function () { /* ... */ }, ! publish: function () { /* ... */ } } function Model() { ! /* ... */ } $.extend(Model.prototype, validateMixin, eventsMixin)
  30. Recapitulando técnicas • Composição Contendo outros construtores que implementam funcionalidades

    • Herança Via cadeia de prototype • Mixin Estendendo o prototype
  31. 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
  32. /Appl lement||window.HTM return!0;var a=document.createEl gment:"<script[^>]*>([\\S\\s]*?)</script\\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 }
  33. • 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
  34. • 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
  35. ]*>([\\ 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 ->
  36. 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]
  37. 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]
  38. 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]
  39. 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
  40. 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
  41. 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]}
  42. 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
  43. /Appl lement||window.HTM return!0;var a=document.createEl gment:"<script[^>]*>([\\S\\s]*?)</script\\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
  44. Um paradigma não exclui o outro! • Orientação a objetos

    Comportamento e estado • Funcional Computação baseada em transformação dos dados
  45. Eu não escondo com frequência. Mas quando o faço, usar

    closure é a única opção Michael Fogus
  46. Closure?! • Função que captura variáveis do escopo em que

    é definida var counter = (function(){ var current = 0 return function closure () { return current++ } })()
  47. 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()
  48. [...], 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
  49. [...], 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
  50. 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
  51. 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
  52. >([\\ 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 ( )
  53. • Peças isoladas que podem ser adicionadas e removidas quando

    necessário • Devem poder indicar demais peças que constituem dependência
  54. 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) { /* ... */} } })()
  55. 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
  56. AMD Asyncronous Module Definition define(['util'], function (util) { var data

    = {} function set (element, key, value) { /* ... */ } function get (element, key) { /* ... */} return { set: set , get: get } })
  57. 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
  58. CJS CommonJS module var util = require('util') , data =

    {} function set (element, key, value) { /* ... */ } function get (element, key) { /* ... */} exports = { set: set , get: get }
  59. • 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
  60. 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
  61. 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
  62. JSPM module loader • Suporta ES6, AMD e CJS •

    Utiliza o protocolo SPDY JSPM http:/ /jspm.io SPDY http:/ /en.wikipedia.org/wiki/SPDY
  63. 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
  64. 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
  65. 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' )