├── .gitignore ├── img ├── traduz-ai.png ├── callback-js.png ├── js-prototype.png ├── angularJS-5-exemplos.png ├── node-absolute-begginer.png └── guia-definitivo-angular.png ├── .gitmodules ├── .editorconfig ├── series ├── voce-nao-precisa-de-jquery │ ├── README.md │ ├── 00-intro.md │ ├── 01-seletores.md │ └── 02-manipulacao-dom.md └── entao-voce-quer-ser-um-programador-funcional │ ├── README.md │ ├── parte-3.md │ ├── parte-4.md │ ├── parte-2.md │ └── parte-1.md ├── angularjs ├── README.md ├── 005-entendendo-diretivas.md └── 002-aprenda-angularjs-com-5-exemplos.md ├── README.md ├── react └── 01-sua-linha-do-tempo-para-aprender-react.md ├── javascript ├── 009-uma-suave-introducao-ao-javascript-parte-1.md ├── 004-entenda-closures-no-javaScript-com-facilidade.md ├── 008-programacao-funcional-prioridade-2015.md ├── 003-escopo-de-variavel-js-e-hoisting-explicado.md ├── 010-uma-suave-introducao-ao-javascript-parte-2.md ├── 012-uma-suave-introducao-ao-javascript-parte-4.md ├── 005-prototipos-javascript-em-uma-linguagem-simples.md └── 007-um-mergulho-no-javascript-puro.md ├── MongoDB └── 001-uma-introdução-ao-mongodb.md └── nodejs └── 001-guia-para-iniciantes-absolutos-em-nodejs.md /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.sw* 3 | -------------------------------------------------------------------------------- /img/traduz-ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angularbrasil/artigos/HEAD/img/traduz-ai.png -------------------------------------------------------------------------------- /img/callback-js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angularbrasil/artigos/HEAD/img/callback-js.png -------------------------------------------------------------------------------- /img/js-prototype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angularbrasil/artigos/HEAD/img/js-prototype.png -------------------------------------------------------------------------------- /img/angularJS-5-exemplos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angularbrasil/artigos/HEAD/img/angularJS-5-exemplos.png -------------------------------------------------------------------------------- /img/node-absolute-begginer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angularbrasil/artigos/HEAD/img/node-absolute-begginer.png -------------------------------------------------------------------------------- /img/guia-definitivo-angular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angularbrasil/artigos/HEAD/img/guia-definitivo-angular.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "javascript/mdo-code-guide"] 2 | path = javascript/mdo-code-guide 3 | url = git@github.com:diegoeis/code-guide.git 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | charset = utf-8 4 | end_of_line = lf 5 | insert_final_newline = false 6 | trim_trailing_whitespace = true 7 | indent_style = tab 8 | indent_size = 4 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /series/voce-nao-precisa-de-jquery/README.md: -------------------------------------------------------------------------------- 1 | # Você não precisa mais de jQuery 2 | 3 | Tradução da série de artigos feito por [Ray Nicholus](https://twitter.com/raynicholus) 4 | 5 | * [Introdução](./00-intro.md) 6 | * [Seletores](./01-seletores.md) 7 | * [DOM](./02-manipulacao-dom.md) -------------------------------------------------------------------------------- /series/entao-voce-quer-ser-um-programador-funcional/README.md: -------------------------------------------------------------------------------- 1 | # Então você quer ser um Programador Funcional? 2 | 3 | Tradução da série de artigos feito por [Charles Scalfani](https://twitter.com/cscalfani) 4 | 5 | * [Parte 1](./parte-1.md) 6 | * [Parte 2](./parte-2.md) 7 | * [Parte 3](./parte-3.md) -------------------------------------------------------------------------------- /angularjs/README.md: -------------------------------------------------------------------------------- 1 | Lista 2 | 3 | - [001-guia-definitivo-para-aprender-angularjs](https://github.com/angularjsbrasil/traduz-ai/blob/master/angularjs/001-guia-definitivo-para-aprender-angularjs.md) 4 | - [002-aprenda-angularjs-com-5-exemplos](https://github.com/angularjsbrasil/traduz-ai/blob/master/angularjs/002-aprenda-angularjs-com-5-exemplos.md) 5 | - [003-use-angularjs-para-potencializar-sua-webapp](https://github.com/angularjsbrasil/traduz-ai/blob/master/angularjs/003-use-angularjs-para-potencializar-sua-webapp.md) 6 | - [004-mais-magicas-angularjs-para-turbinar-sua-webapp](https://github.com/angularjsbrasil/traduz-ai/blob/master/angularjs/004-mais-magicas-angularjs-para-turbinar-sua-webapp.md) 7 | -------------------------------------------------------------------------------- /angularjs/005-entendendo-diretivas.md: -------------------------------------------------------------------------------- 1 | # Entendendo Diretivas 2 | 3 | * **Artigo Original**: [Understanding Directives](https://github.com/angular/angular.js/wiki/Understanding-Directives) 4 | * **Tradução**: [Eric Douglas](https://github.com/ericdouglas) 5 | 6 | Este documento é uma tentativa de explicar como as Diretivas no AngularJS e suas engines compiladoras relacionadas trabalham, para que você não sinta que está se deparando com *um macarrão* a primeira vez que tentar resolver isso sozinho. 7 | 8 | ## Injetando, Compilando e Linkando funções 9 | 10 | Quando você cria uma diretiva, existem essencialmente 3 camadas de função que para você definir: 11 | 12 | ```js 13 | myApp.directive('uiJq', function InjectingFunction() { 14 | 15 | // === InjectingFunction === // 16 | // Lógica é executada 0 ou 1 vez por app 17 | // (dependendo se a diretiva é usada) 18 | // Útil para inicialização e configuração global 19 | 20 | return { 21 | compile: function CompilingFunction($templateElement, $templateAttributes) { 22 | 23 | // === CompilingFunction === // 24 | // Lógica é executada uma vez para cada instância de ui-jq no seu template original NÃO RENDERIZADO 25 | // Escopo está INDISPONÍVEL quando os modelos estão sendo cacheados. 26 | // Você PODE examinar o DOM e informação de cache sobre as variáveis ou expressões 27 | // que você vai usar, mas ainda não consegue descobrir seus valores 28 | // Angular está cacheando os templates, agora é uma boa hora de injetar novos templates do Angular 29 | // como filhos ou futuros irmãos para rodarem automaticamente. 30 | 31 | return function LinkingFunction($scope, $linkElement, $linkAttributes) { 32 | 33 | // === LinkingFunction === // 34 | // A lógica é executada uma vez para cada instância renderizada 35 | // 36 | }; 37 | 38 | } 39 | }; 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /series/voce-nao-precisa-de-jquery/00-intro.md: -------------------------------------------------------------------------------- 1 | # Você não precisa de jQuery (Não mais) 2 | 3 | * **Artigo original**: [You Don't Need jQuery (anymore)](http://blog.garstasio.com/you-dont-need-jquery/why-not/) 4 | * **Tradução**: [Gabriel](https://github.com/BielRibeiro) 5 | 6 | **Muitos** desenvolvedores web dependem do jQuery. Para muitos, jQuery e Javascript parecem ser a mesma coisa. Então, por que não usá-lo? Por que parar de usá-lo? Você simplesmente não precisa dele? 7 | 8 | Com jQuery tudo fica mais fácil. Você não consegue desenvolver uma web app sólida sem ele. É muito difícil garantir que seu app funcionará corretamente em todos os browsers sem jQuery - A implementação da [Web API](http://en.wikipedia.org/wiki/Web_API) varia muito entre os browsers. 9 | Todos os bons plug-ins que eu preciso, dependem do jQuery de qualquer maneira. 10 | 11 | Usei estas desculpas acima durante a maior parte da minha carreira. E algumas delas foram, por um momento, boas desculpas. Em 2012, quando assumi a manutenção e o desenvolvimento de uma [grande biblioteca de file upload](https://github.com/FineUploader), [meu primeiro instinto foi o de reescrever tudo usando jQuery](https://github.com/FineUploader/fine-uploader/issues/326), porque eu pensei que aquilo facilitaria minha vida. A comunidade de usuários existente foi contra trazer qualquer outra dependência para a biblioteca, então fui forçado a lidar com a API nativa do browser. E quer saber? Foi mais fácil colocar o jQuery de lado do que eu imaginei. Eu não precisava do jQuery, e nem você precisa. 12 | 13 | ## A Armadilha 14 | 15 | Há algum tempo, quando entrei no mundo do desenvolvimento web, a primeira biblioteca que usei foi o jQuery. Na verdade, nunca me importei em aprender Javascript direito. Eu não tinha a menor ideia de como era a Web API, ou como mexer no DOM precisamente. O jQuery fez tudo por mim. Fui pego por esta enorme lacuna em meu conhecimento quando entrei em um projeto sem jQuery. Fui forçado a aprender desenvolvimento web direito, e nunca mais olhei para trás. 16 | 17 | Cai numa armadilha que muitos desenvolvedores web novos, casuais e amadores caem. Se primeiramente tivesse gasto meu tempo para aprender Javascript e a API do browser, teria evitado muitos problemas. A sequência correta de estudos é: 18 | 19 | 1. Aprender Javascript 20 | 2. Aprender sobre a Web API 21 | 3. Aprender jQuery (ou qualquer outro framework/biblioteca que você pode precisar nos projetos) 22 | 23 | Alguns começam com o #3 e #1, e o #2 vem somente depois (ou nunca). Se você não entende o que o jQuery na verdade está fazendo por você, haverão muitos dias frustrantes a frente, descobrindo ["vazamentos" em sua abstração](http://www.joelonsoftware.com/articles/LeakyAbstractions.html), ou no caso de você não poder usar jQuery em um projeto futuro. Esta é uma armadilha que você precisa evitar se quiser crescer efetivamente como desenvolvedor web. 24 | 25 | ## Suporte Cross-Browser 26 | 27 | Uma das razões mais usadas para valorizar o jQuery é a de arrumar a API fraca do DOM. Este é um ponto válido, mas somente se você estiver trabalhando com o IE7 ou anterior. 28 | Estamos em 2014, e o suporte a IE7 é raro. A API do DOM não é tão ruim como muitas pessoas costuman dizer. Percorrer, manipular e criar elementos é consistentemente suportado por todos os browsers modernos. 29 | 30 | A Web API como um todo é, de certa forma, bastante avançada e capaz desde o IE8. É claro, existem falhas nos browsers pré-IE10 e em algumas implementações muito antigas do Safari/Webkit, mas estas falhas podem ser solucionadas, conforme a necessidade, com bibliotecas pequenas e específicas. Em alguns casos, como o suporte cross-browser do file upload, suporte a MutationObserver ou suporte a Web Component, você precisará integrar outras bibliotecas fora o jQuery. O ponto é que jQuery não é bala de prata, e existe uma boa chance de você precisar somente de uma pequena parte do que o jQuery oferece. 31 | 32 | ## JavaScript 33 | 34 | Outra razão comum para se usar o jQuery, é a de usar atalhos para a linguagem que está por debaixo dos panos (Javascript). Esta é uma das desculpas mais esfarrapadas. É um pouco demais usar uma dependência como o jQuery simplesmente por uma maneira "melhor" de percorrer as propriedades de um objeto ou um array de elementos. Na verdade, isto é completamente desnecessário levando em conta a existência de forEach e Object.keys() (ambos disponíveis em IE9+). Ou talvez você ache que inArray() é útil? Não desde o IE9, onde [Array.prototype.indexOf](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.14) ficou disponível como parte do ES5. Existem muitos exemplos, mas eu vou guardá-los para um próximo post. 35 | 36 | ## Ok, mas eu preciso mesmo abandonar o jQuery? 37 | 38 | Mas é claro que não. Se você se sente confortável com o jQuery, e está familiar o suficiente em como o jQuery faz sua mágica, então continue usando. 39 | Esta série de posts é sobre como lhe capacitar para usar a Web API e (quando preciso) bibliotecas específicas para resolver problemas em seus web apps sem depender de grandes bibliotecas com vários propósitos que, na sua maioria, nem serão utilizados. 40 | 41 | ## Ok, mas eu devo abandonar o jQuery? 42 | 43 | Isto é com você. Esta série toda é para mostrar a Web API e o vanilla Javascript. A resposta é **não** se você precisa dar suporte a browsers muito antigos e o jQuery faz sua vida mais fácil. Porém, se você pode suportar versões de browsers mais atuais, e/ou fica feliz em escrever seu próprio código, deixe o jQuery de lado. 44 | 45 | ## Próximo Post 46 | 47 | [Selecting elements without jQuery.](http://blog.garstasio.com/you-dont-need-jquery/selectors/) (Em inglês) 48 | 49 | [Selecionando elementos sem jQuery.](01-seletores.md) (Em português) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | > Coleção de artigos sobre desenvolvimento web traduzidos para pt-br 4 | 5 | ## Como Ajudar 6 | 7 | Além dos materiais separados para tradução, você pode contribuir através da indicação de novos artigos para as traduções e/ou com as traduções/revisões. Deixe sua contribuição **[aqui](https://github.com/ericdouglas/traduz-ai/issues)**. 8 | 9 | ## Tópicos 10 | 11 | * [AngularJS](#angularjs) (05) 12 | * [Behaviour Driven Development](#behaviour-driven-development) (01) 13 | * [Handlebars](#handlebarsjs) (01) 14 | * [JavaScript](#javascript) (12) 15 | * [MongoDB](#mongodb) (01) 16 | * [Node.js](#nodejs) (02) 17 | * [React](#react) (02) 18 | 19 | ## Séries 20 | 21 | * [Você não precisa de jQuery](series/voce-nao-precisa-de-jquery) `javascript` 22 | * [Então você quer ser um Programador Funcional?](series/entao-voce-quer-ser-um-programador-funcional) `javascript` `programação funcional` 23 | 24 | ### AngularJS 25 | 26 | 1. Guia Definitivo para Aprender AngularJS em Um Dia - [`Tradução`](angularjs/001-guia-definitivo-para-aprender-angularjs.md) [`Original`](http://toddmotto.com/ultimate-guide-to-learning-angular-js-in-one-day/) 27 | 1. Aprenda AngularJS com estes 5 exemplos práticos - [`Tradução`](angularjs/002-aprenda-angularjs-com-5-exemplos.md) [`Original`](http://tutorialzine.com/2013/08/learn-angularjs-5-examples/) 28 | 1. Use AngularJS para Potencializar sua Aplicação Web - [`Tradução`](angularjs/003-use-angularjs-para-potencializar-sua-webapp.md#use-angularjs-para-potencializar-suas-aplica%C3%A7%C3%B5es-web) [`Original`](http://www.yearofmoo.com/2012/08/use-angularjs-to-power-your-web-application.html) 29 | 1. Mais mágicas do AngularJS para turbinar sua Webapp - [`Tradução`](angularjs/004-mais-magicas-angularjs-para-turbinar-sua-webapp.md#mais-m%C3%A1gicas-do-angularjs-para-turbinar-sua-webapp) [`Original`](http://www.yearofmoo.com/2012/10/more-angularjs-magic-to-supercharge-your-webapp.html) 30 | 1. Entendendo Diretivas - [`Tradução`](angularjs/005-entendendo-diretivas.md) [`Original`](https://github.com/angular/angular.js/wiki/Understanding-Directives) 31 | 32 | ### Behaviour Driven Development 33 | 34 | 1. Behaviour Driven Development com JavaScript - [`Tradução`](bdd/001-bdd-with-js.md) [`Original`](http://gajus.com/blog/1/behaviour-driven-development-with-javascript) 35 | 36 | ### Handlebars.js 37 | 38 | 1. Aprenda Tudo sobre Handlebars.js Templating JavaScript - [`Tradução`](handlebars/001-aprenda-tudo-sobre-handlebars.md#aprenda-tudo-sobre-handlebarsjs-templating-javascript) [`Original`](http://javascriptissexy.com/handlebars-js-tutorial-learn-everything-about-handlebars-js-javascript-templating/) 39 | 40 | ### JavaScript 41 | 42 | 1. Como Aprender JavaScript Corretamente - [`Tradução`](javascript/001-como-aprender-js-corretamente.md#como-aprender-javascript-corretamente--javascriptis-sexy) [`Original`](http://javascriptissexy.com/how-to-learn-javascript-properly/) 43 | 1. Objetos JavaScript em Detalhe - [`Tradução`](javascript/002-objetos-js-em-detalhe.md#objetos-javascript-em-detalhe) [`Original`](http://javascriptissexy.com/javascript-objects-in-detail/) 44 | 1. Escopo de Variável e Hoisting no JavaScript Explicado - [`Tradução`](javascript/003-escopo-de-variavel-js-e-hoisting-explicado.md#escopo-de-vari%C3%A1vel-javascript-e-hoisting-explicado) [`Original`](http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/) 45 | 1. Entenda Closures no JavaScript com Facilidade - [`Tradução`](javascript/004-entenda-closures-no-javaScript-com-facilidade.md#entenda-closures-no-javascript-com-facilidade) [`Original`](http://javascriptissexy.com/understand-javascript-closures-with-ease/) 46 | 1. Protótipos JavaScript em uma Linguagem Simples - [`Tradução`](javascript/005-prototipos-javascript-em-uma-linguagem-simples.md#prot%C3%B3tipos-javascript-em-uma-linguagem-simples) [`Original`](http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/) 47 | 1. Entenda Funções Callback no JavaScript e Use-as - [`Tradução`](javascript/006-entenda-callbacks-js.md) [`Original`](http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/) 48 | 1. Um Mergulho no JavaScript Puro - [`Tradução`](javascript/007-um-mergulho-no-javascript-puro.md) [`Original`](http://blog.adtile.me/2014/01/16/a-dive-into-plain-javascript/) 49 | 1. Programação Funcional Deve Ser Sua Prioridade número #1 em 2015 - [`Tradução`](javascript/008-programacao-funcional-prioridade-2015.md) [`Original`](https://medium.com/@jugoncalves/functional-programming-should-be-your-1-priority-for-2015-47dd4641d6b9) 50 | 1. Uma Suave Introdução ao JavaScript Funcional: Parte 1 - [`Tradução`](javascript/009-uma-suave-introducao-ao-javascript-parte-1.md) [`Original`](http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-intro/) 51 | 1. Uma Suave Introdução ao JavaScript Funcional: Parte 2 - [`Tradução`](javascript/010-uma-suave-introducao-ao-javascript-parte-2.md) [`Original`](http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-arrays/) 52 | 1. Uma Suave Introdução ao JavaScript Funcional: Parte 3 - [`Tradução`](javascript/011-uma-suave-introducao-ao-javascript-parte-3.md) [`Original`](http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-functions/) 53 | 1. Uma Suave Introdução ao JavaScript Funcional: Parte 4 - [`Tradução`](javascript/012-uma-suave-introducao-ao-javascript-parte-4.md) [`Original`](http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-style/) 54 | 55 | ### MongoDB 56 | 57 | 1. Uma introdução ao MongoDB - [`Tradução`](MongoDB/001-uma-introdução-ao-mongodb.md) [`Original`](https://scotch.io/tutorials/an-introduction-to-mongodb) 58 | 59 | ### Node.js 60 | 61 | 1. Guia Para Absolutos Iniciantes em Node.js - [`Tradução`](nodejs/001-guia-para-iniciantes-absolutos-em-nodejs.md) [`Original`](http://blog.modulus.io/absolute-beginners-guide-to-nodejs) 62 | 1. Guia para um dev. front-end iniciar Com Node.js, Express, Jade e MongoDB - [`Tradução`](nodejs/002-simples-guia-nodejs-jade-express-mongodb.md) [`Original`](http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/) 63 | 64 | ### React 65 | 66 | 1. Sua Linha do Tempo para Aprender React - [`Tradução`](react/01-sua-linha-do-tempo-para-aprender-react.md) [`Original`](https://daveceddia.com/timeline-for-learning-react/) 67 | 1. Introdução ao React para pessoas que sabem apenas o suficiente de jQuery para sobreviver - [`Tradução`](react/02-introducao-ao-react-para-pessoas-que-sabem-apenas-jquery.md) [`Original`](http://reactfordesigners.com/labs/reactjs-introduction-for-people-who-know-just-enough-jquery-to-get-by/) 68 | 69 | ## Outros Projetos 70 | 71 | * [You Don't Know JS](https://github.com/cezaraugusto/You-Dont-Know-JS) 72 | * [Wisdom of the elePHPant](https://github.com/reginaldojunior/wisdom-of-the-elephant) 73 | -------------------------------------------------------------------------------- /series/voce-nao-precisa-de-jquery/01-seletores.md: -------------------------------------------------------------------------------- 1 | # Selecionando elementos sem jQuery 2 | 3 | * **Artigo original**: [Selecting Elements](http://blog.garstasio.com/you-dont-need-jquery/selectors/) 4 | * **Tradução**: [Gabriel](https://github.com/BielRibeiro) 5 | 6 | Quantas vezes você viu uma web app ou biblioteca que usa jQuery simplesmente para selecionar elementos? Quantas vezes você escreveu isto: ```$(#meuElemento')```? Ou isto: ```$('.meuElemento')```? Psst... Você não precisa de jQuery para selecionar elementos! Isto já é muito fácil simplesmente usando a DOM API. 7 | 8 | 1. [IDs](#ids) 9 | 2. [Classes CSS](#classes-css) 10 | 3. [Nome da Tag](#tag-name) 11 | 4. [Atributos](#atributos) 12 | 5. [Pseudo-classes](#pseudo-classes) 13 | 6. [Filhos](#filhos) 14 | 7. [Descendentes](#descendentes) 15 | 8. [Seletores de Exclusão](#seletores-exclusao) 16 | 9. [Seletores Múltiplos](#seletores-multiplos) 17 | 10. [Vê um padrão?](#padrao) 18 | 11. [Mas Eu Quero Mais](#quero-mais) 19 | 12. [Próximo](#proximo) 20 | 21 | ## Por ID 22 | 23 | *jQuery* 24 | 25 | ``` 26 | // retorna um objeto jQuery com 0-1 elementos 27 | $('#meuElemento'); 28 | ``` 29 | 30 | *DOM API* 31 | 32 | ``` 33 | // IE 5.5+ 34 | document.getElementById('meuElemento'); 35 | ``` 36 | 37 | ... ou ... 38 | 39 | ``` 40 | // IE 8+ 41 | document.querySelector('#meuElemento'); 42 | ``` 43 | 44 | Ambos os métodos retornam um único elemento. Perceba que [getElementById é mais eficiente do que usar querySelector](http://jsperf.com/getelementbyid-vs-queryselector/11). 45 | 46 | Será que o jQuery proporciona alguma vantagem aqui? Eu não vejo nenhuma. Você vê? 47 | 48 | ## Por classe CSS 49 | 50 | *jQuery* 51 | 52 | ``` 53 | // retorna um objeto jQuery com todos elementos correspondentes 54 | $('.meuElemento'); 55 | ``` 56 | 57 | *DOM API* 58 | 59 | ``` 60 | // IE 9+ 61 | document.getElementsByClassName('meuElemento'); 62 | ``` 63 | 64 | ... ou ... 65 | 66 | ``` 67 | // IE 8+ 68 | document.querySelectorAll('.meuElemento'); 69 | ``` 70 | 71 | O primeiro método retorna uma [HTMLCollection](https://developer.mozilla.org/pt-BR/docs/Web/API/HTMLCollection) e é o [mais eficiente entre as duas escolhas](http://jsperf.com/getelementsbyclassname-vs-queryselectorall/25). O método querySelectorAll sempre retorna uma [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList). 72 | 73 | Novamente nada complicado. Por que se preocupar com jQuery? 74 | 75 | ## Por Nome da Tag 76 | 77 | Para selecionar todas as ```
24 |
25 | function validateSsn(ssn) {
26 | if (/^\d{3}-\d{2}-\d{4}$/.exec(ssn))
27 | console.log('Valid SSN');
28 | else
29 | console.log('Invalid SSN');
30 | }
31 | function validatePhone(phone) {
32 | if (/^\(\d{3}\)\d{3}-\d{4}$/.exec(phone))
33 | console.log('Valid Phone Number');
34 | else
35 | console.log('Invalid Phone Number');
36 | }
37 |
38 |
39 |
40 | Todos nós já escrevemos código como este ao longo do tempo, começamos a reconhecer que estas duas funções são praticamente iguais e diferenciam-se somente por algumas coisas (mostradas em **negrito**).
41 |
42 | Ao invés de copiar **validadeSsn**, colar e editar para criar **validatePhone**, nós deveríamos criar uma única função e parametrizar as coisas que nós editamos depois de colar.
43 |
44 | Neste exemplo, nós passaríamos como parâmetro o **value**, a **regular expression** e a **mensagem** (pelo menos a última parte da mensagem).
45 |
46 | O código refatorado:
47 |
48 |
49 |
50 | function validateValue(value, regex, type) {
51 | if (regex.exec(value))
52 | console.log('Invalid ' + type);
53 | else
54 | console.log('Valid ' + type);
55 | }
56 |
57 |
58 |
59 | Os parâmetros **ssn** e **phone** no código antigo, agora são representados pelo **value**.
60 |
61 | As expressões regulares **/^\d{3}-\d{2}-\d{4}$/** e **/^\(\d{3}\)\d{3}-\d{4}$/** são representadas pelo **regex**.
62 |
63 | E por último, a última parte da mensagem **SSN** e **'Phone Number'** são representados pelo **type**.
64 |
65 | Ter uma função é muito melhor do que ter duas funções. Ou pior, três, quatro ou dez funções. Isto mantém seu código limpo e fácil de manter.
66 |
67 | Por exemplo, se houver um bug, você precisa arrumar somente em um lugar versus procurar por todo o codebase para para achar o lugar onde esta função PODE ter sido posta e modificada.
68 |
69 | Mas o quê acontece quando você tem a seguinte situação:
70 |
71 |
72 |
73 | function validateAddress(address) {
74 | if (parseAddress(address))
75 | console.log('Valid Address');
76 | else
77 | console.log('Invalid Address');
78 | }
79 | function validateName(name) {
80 | if (parseFullName(name))
81 | console.log('Valid Name');
82 | else
83 | console.log('Invalid Name');
84 | }
85 |
86 |
87 |
88 | Aqui **parseAddress** e **parseFullName** são funções que recebem uma **string** e retornam **true** se ela for analisada.
89 |
90 | Como refatoramos isto?
91 |
92 | Bem, nós podemos usar **value** para **address** e **name**, e **type** para **'Address'** e **'Name'** como fizemos antes mas existe uma função onde nossa expressão regular costumava estar.
93 |
94 | Se nós somente pudéssemos passar uma função como parâmetro...
95 |
96 | ### High-Order Functions
97 |
98 | Muitas linguagens não suportam passar funções como parâmetros. Algumas sim mas elas não facilitam.
99 |
100 | > Em Programação Funcional, uma função é um cidadão de primeira classe da linguagem. Em outras palavras, uma função é somente outro valor.
101 |
102 | Uma vez que função são somente valores, podemos passá-las como parâmetros.
103 |
104 | Mesmo que a Javascript não seja uma Linguagem Puramente Funcional, você pode fazer algumas operações funcionais com ela. Então aqui estão as últimas duas funções refatoradas em uma única função passando a **função de parse** como parâmetro chamado **parseFunc**:
105 |
106 |
107 |
108 | function validateValueWithFunc(value, parseFunc, type) {
109 | if (parseFunc(value))
110 | console.log('Invalid ' + type);
111 | else
112 | console.log('Valid ' + type);
113 | }
114 |
115 |
116 |
117 | Nossa nova função é chamada de **High-order Function**.
118 |
119 | > High-order Functions também recebe funções como parâmetros, retorna funções ou ambas.
120 |
121 | Agora podemos chamar nossa high-order function para as 4 funções anteriores (isto funciona na Javascript porque **Regex.exe** retorna um valor verdadeiro quando uma combinação é encontrada):
122 |
123 | ```
124 | validateValueWithFunc('123-45-6789', /^\d{3}-\d{2}-\d{4}$/.exec, 'SSN');
125 | validateValueWithFunc('(123)456-7890', /^\(\d{3}\)\d{3}-\d{4}$/.exec, 'Phone');
126 | validateValueWithFunc('123 Main St.', parseAddress, 'Address');
127 | validateValueWithFunc('Joe Mama', parseName, 'Name');
128 | ```
129 |
130 | Isto é muito melhor do que ter 4 funções identicas.
131 |
132 | Mas note as expressões regulares. Elas são um pouco verbosas. Vamos limpar nosso código refatorando-o:
133 |
134 |
135 |
136 | var parseSsn = /^\d{3}-\d{2}-\d{4}$/.exec;
137 | var parsePhone = /^\(\d{3}\)\d{3}-\d{4}$/.exec;
138 | validateValueWithFunc('123-45-6789', parseSsn, 'SSN');
139 | validateValueWithFunc('(123)456-7890', parsePhone, 'Phone');
140 | validateValueWithFunc('123 Main St.', parseAddress, 'Address');
141 | validateValueWithFunc('Joe Mama', parseName, 'Name');
142 |
143 |
144 |
145 | Assim está melhor. Agora quando queremos analisar um número de telefone, não precisamos copiar e colar a expressão regular.
146 |
147 | Mas imagine que temos mais expressões regulares para analisar, não somente **parseSsn** e **parsePhone**. Cada vez que criamos um analisador de expressão regular, temos que lembrar de adicionar o **.exec** no final. E acredite, isto é fácil de esquecer.
148 |
149 | Podemos nos proteger disso criando uma high-order function que retorna a função **exec**:
150 |
151 |
152 |
153 | function makeRegexParser(regex) {
154 | return regex.exec;
155 | }
156 | var parseSsn = makeRegexParser(/^\d{3}-\d{2}-\d{4}$/);
157 | var parsePhone = makeRegexParser(/^\(\d{3}\)\d{3}-\d{4}$/);
158 | validateValueWithFunc('123-45-6789', parseSsn, 'SSN');
159 | validateValueWithFunc('(123)456-7890', parsePhone, 'Phone');
160 | validateValueWithFunc('123 Main St.', parseAddress, 'Address');
161 | validateValueWithFunc('Joe Mama', parseName, 'Name');
162 |
163 |
164 |
165 | Aqui, **makeRegexParser** recebe uma expressão regular e retorna a função **exec**, que recebe uma string. **validateValueWithFunc** passará a string, **value**, para a função de parse, isto é **exec**.
166 |
167 | **parseSsn** e **parsePhone** são efetivamente as mesmas de antes, a função **exec** da expressão regular.
168 |
169 | Isto é uma ligeira melhoria, mas é mostrada aqui para dar um exemplo de high-order function que retorna uma função.
170 |
171 | Contudo, você pode imaginar os benefícios de fazer esta mudança caso **makeRegexParser** fosse mais complexa.
172 |
173 | Aqui está um outro exemplo de high-order function que retorna uma função:
174 |
175 | ```
176 | function makeAdder(constantValue) {
177 | return function adder(value) {
178 | return constantValue + value;
179 | };
180 | }
181 | ```
182 |
183 | Aqui temos **makeAdder** que recebe **constantValue** e retorna **adder**, uma função que irá adicionar essa constante para qualquer valor que for passado.
184 |
185 | Aqui está como pode ser usada:
186 |
187 | ```
188 | var add10 = makeAdder(10);
189 | console.log(add10(20)); // prints 30
190 | console.log(add10(30)); // prints 40
191 | console.log(add10(40)); // prints 50
192 | ```
193 |
194 | Nós criamos uma função, **add10**, passando a constante **10** para **makeAdder** que retorna a função que irá somar **10** para tudo.
195 |
196 | Perceba que a função **adder** tem acesso a **constantValue** mesmo depois de **makeAdder** retorna. Isto é porque **constantValue** estava em seu escopo quando **adder** foi criado.
197 |
198 | Este comportamento é bastante importante porque sem ele, funções que retornam funções não seriam muito úteis. Então é importante entendermos como elas funcionam e como este comportamento é chamado.
199 |
200 | Este comportamento é chamado de **Closure**.
201 |
202 | ### Closures
203 |
204 | Aqui está um exemplo planejado para mostrar o uso de closures:
205 |
206 |
207 |
208 | function grandParent(g1, g2) {
209 | var g3 = 3;
210 | return function parent(p1, p2) {
211 | var p3 = 33;
212 | return function child(c1, c2) {
213 | var c3 = 333;
214 | return g1 + g2 + g3 + p1 + p2 + p3 + c1 + c2 + c3;
215 | };
216 | };
217 | }
218 |
219 |
220 |
221 | Neste exemplo, **child** tem acesso as suas variáveis, as variáveis de **parent** e **grandParent**.
222 |
223 | A **parent** tem acesso as suas variáveis e as da **grandParent**.
224 |
225 | A **grandParent** tem acesso somente as suas variáveis.
226 |
227 | (Veja a pirâmide acima para esclarecimento.)
228 |
229 | Aqui está um exemplo de seu uso:
230 |
231 | ```
232 | var parentFunc = grandParent(1, 2); // returns parent()
233 | var childFunc = parentFunc(11, 22); // returns child()
234 | console.log(childFunc(111, 222)); // prints 738
235 | // 1 + 2 + 3 + 11 + 22 + 33 + 111 + 222 + 333 == 738
236 | ```
237 |
238 | Aqui, **parentFunc** mantém o escopo de **parent** vivo visto que **grandParent** retorna **parent**.
239 |
240 | Do mesmo modo, **childFunc** mantém o escopo de **child** vivo visto que **parentFunc** que é apenas **parent**, retorna **child**.
241 |
242 | Quando uma função é criada, todas as variáveis em seu escopo **em tempo de criação** são acessíveis a ela pelo tempo de vida da função. Uma função existe enquanto houver uma referência à ela. Por exemplo, o escopo de **child** existe enquanto **childFunc** referenciá-lo.
243 |
244 | > Uma closure é um escopo de uma função que é mantido vivo por uma referência àquela função.
245 |
246 | Note que na Javascript, closures são problemáticas visto que as variáveis são mutáveis, isto é, elas podem mudar de valor do tempo em que elas foram "enclausuradas" para o tempo que a função retornada é chamada.
247 |
248 | Agradecidamente, variáveis em Linguagens Funcionais são imutáveis, eliminando esta fonte comum de bugs e confusão.
249 |
250 | ### Meu cérebro!!!
251 |
252 | Por enquanto chega.
253 |
254 | Nas próximas partes deste artigo, eu vou falar sobre Functional Composition, Currying, funções funcionais comuns (ex: map, filter, fold etc.), e mais.
255 |
256 | A seguir:
257 |
258 | [Parte 3](parte-3.md) (em português)
259 | [Parte 3](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-3-1b0fd14eb1a7#.zffq7cklj) (em inglês)
260 |
--------------------------------------------------------------------------------
/javascript/008-programacao-funcional-prioridade-2015.md:
--------------------------------------------------------------------------------
1 | # Programação Funcional Deve Ser Sua Prioridade número #1 em 2015
2 | ### - OOP não pode mais nos salvar do *Cloud Monster*
3 |
4 | * **Artigo Original**: [Functional Programming should be your #1 priority for 2015](https://medium.com/@jugoncalves/functional-programming-should-be-your-1-priority-for-2015-47dd4641d6b9)
5 | * **Tradução**: [Eric Douglas](https://github.com/ericdouglas) e [Diogo Beato](https://github.com/diogobeato)
6 |
7 | Você provavelmente já ouviu expressões como "Clojure", "Scala", "Erlang", ou mesmo "Java agora tem *lambdas*". E você deve saber que isso tem alguma coisa a ver com "Programação Funcional". Se você participa de qualquer comunidade de programação, esse assunto provavelmente apareceu alguma vez.
8 |
9 | Se você já buscou por "Functional Programming" (ou Programação Funcional), viu que não existe nada de novo. A segunda linguagem criada já utilizava isso, apareceu por volta da década de 50, nominada *Lisp*. Por que, então, as pessoas estão empolgadas com isso apenas agora? Quase 60 anos depois!?
10 |
11 | ## No início, os computadores eram realmente lentos
12 |
13 | Acredite nisso ou não, computadores eram muuuuito mais lentos que o DOM. Não, sério. E naquele tempo, existiam duas mentalidades principais em termos de arquitetura e implementação de linguagens de programação:
14 |
15 | 1. Iniciar pela Arquitetura Von Neumann e adicionar abstração.
16 | 1. Iniciar pela Matemática e remover abstração.
17 |
18 | Os computadores não tinham tanto poder de processamento para lidar com abstrações por todo o caminho e executar os programas funcionais. Então, Lisp acabou sendo mortalmente lenta, portanto, não adequada para o trabalho. Foi quando a programação imperativa começou sua dominação, especialmente com a ascenção do *C*.
19 |
20 | ### Mas os computadores melhoraram muito
21 |
22 | Agora é virtualmente possível rodar a maioria das aplicações sem se preocupar muito sobre em qual linguagem foi escrita. Finalmente, linguagens funcionais tiveram sua segunda chance.
23 |
24 | ## Programação Funcional 50.5
25 |
26 | Isso não é uma introdução a *FP* (*Functional Programming*). No fim dessa seção, você deverá ter uma ideia de o que *FP* é e como começar sua jornada.
27 |
28 | Você pode entender Programação Funcional por programação com funções, que é, de fato, muito mais literal do que você pode imaginar agora. Você vai criar funções em termos de outras funções e compor funções (Você se lembra `f ∘ g` da escola? Isso vai ser útil agora).
29 |
30 | Aqui temos uma (não-exaustiva) lista de características da FP:
31 |
32 | 1. First-Class Functions (Funções de Primeira Classe)
33 | 1. High-Order Functions (Funções de Alta Ordem)
34 | 1. Pure Functions (Funções Puras)
35 | 1. Closures
36 | 1. Immutable State (Imutabilidade de Estado)
37 |
38 | Você não deve se preocupar com nomes *sofisticados* agora: apenas entenda o que eles significam.
39 |
40 | **First-Class Functions**, ou *Funções de Primeira Classe*, significa que você vai armazenar funções dentro de uma variável. Acredito que você já fez algo parecido com isso em JavaScript:
41 |
42 | ```js
43 | var add = function(a, b){
44 | return a + b
45 | }
46 | ```
47 |
48 | Você está apenas armazenando uma função anônima que recebe `a` e `b`, e retorna `a + b`, dentro de uma variável denominada `add`.
49 |
50 | **High-Order Functions**, ou *Funções de Alta Ordem*, significa que funções podem retornar funções ou receber funções como parâmetro.
51 |
52 | Novamente, em JavaScript:
53 |
54 | ```js
55 | document.querySelector('#button')
56 | .addEventListener('click', function(){
57 | alert('yay, i got clicked')
58 | })
59 | ```
60 |
61 | ou
62 |
63 | ```js
64 | var add = function(a){
65 | return function(b){
66 | return a + b
67 | }
68 | }
69 |
70 | var add2 = add(2)
71 | add2(3) // => 5
72 | ```
73 |
74 | Ambos os casos são um exemplo de Funções de Alta Ordem, mesmo que você nunca tenha usado algo parecido com isso, provavelmente você já viu algo assim em algum lugar.
75 |
76 | **Pure Functions**, ou *Funções Puras*, significa que funções não mudam nenhum valor, elas apenas recebem dados e retornam dados, assim como nossas amadas funções da Matemática. Isso também significa que, se você passar `2` para uma função `f` e ela retornar `10`, ela sempre irá retornar `10`. Não importa o ambiente, threads, ou qualquer ordem de avaliação. Ela não causa nenhum efeito colateral em outras partes do programa, e isso é realmente um conceito poderoso.
77 |
78 | **Closures** significa que você pode salvar algum dado dentro de uma função que é apenas acessível à função de retorno, isto é, a função retornada mantém seu ambiente de execução.
79 |
80 | ```js
81 | var add = function(a){
82 | return function(b){
83 | return a + b
84 | }
85 | }
86 |
87 | var add2 = add(2)
88 | add2(3) // => 5
89 | ```
90 |
91 | Verifique o segundo exemplo de *High-Order Function* novamente. A variável foi *fechada* e é acessível somente para a função retornada.
92 |
93 | **Immutable State** ou *Estado Imutável* signifca que você não pode alterar o estado de forma alguma (embora você possa gerar um novo estado). No seguinte código (em OCaml), você pode usar `x` e `5` alternadamente em seu programa. `x` vai sempre ser `5`.
94 |
95 | ```ocaml
96 | let x = 5;;
97 | x = 6;;
98 |
99 | print_int x;; (* prints 5 *)
100 | ```
101 |
102 | Isso parece muito mais com um ponto negativo que uma boa característica, mas você vai ver que isso salvará sua vida.
103 |
104 | ## Programação Orientada a Objetos não pode mais nos salvar
105 |
106 | Aquele momento de que teríamos aplicações concorrentes e distribuídas rodando finalmente chegou.
107 |
108 | Infelizmente, nós não estamos prontos: nosso "atual" (i.e., mais usado) modelo para concorrência e paralelismo, embora resolva o problema, ainda traz muita complexidade.
109 |
110 | Para termos melhores aplicações, precisamos de uma maneira simples e confiável para fazer isto. Você se lembra das features de FP mencionados acima? *Pure Functions* (Funções Puras) e *Immutable State* (Imutabilidade de Estado)? Exatamente. Você pode rodar uma função milhares de vezes em diferentes *cores* ou máquinas que ainda assim não terá resultados diferentes dos que teve anteriormente. Sendo assim, você pode usar o mesmo código para rodar em 1 *core* ou em 1k de *cores*. Podemos ser felizes novamente.
111 |
112 | > "Mas por que eu não posso continuar usando POO?"
113 |
114 | Ao menos para concorrência e paralelismo, POO não pode mais te salvar. Isso porque, POO precisa que haja estados mutáveis. Os métodos dos objetos que você invoca, normalmente, servem para alterar o estado do objeto em questão ou de outro. E, trabalhando com concorrência, precisamos adicionar muita complexidade para mantermos sincronizadas todas as threads que utilizam esses objetos concorrentemente ou paralelamente.
115 |
116 | Eu não estou aqui para argumentar que você deve sair do seu paradigma atual para o FP (mesmo que [algumas pessoas digam pra você fazer](https://blog.inf.ed.ac.uk/sapm/2014/03/06/enemy-of-the-state-or-why-oop-is-not-suited-to-large-scale-software/), mas definitivamente você precisa dominá-lo: O Java 8 e C++11 incorporaram as expressões lambda em suas plataformas. Posso afirmar que toda linguagem moderna e ainda mantida vai contar com features de FP em breve. E a maioria delas já tem.
117 |
118 | Vale a pena mencionar que você não vai parar de usar estados mutáveis. Nós precisamos para desenvolver funcionalidades como IO e etc, para termos bons softwares. Porém, a ideia principal que FP provê é: use estados mutáveis apenas quando for necessário.
119 |
120 | ## Eu não trabalho com Cloud, eu realmente preciso de FP?
121 |
122 | Sim.
123 |
124 | Programação Funcional irá te ajudar a escrever melhores programas e raciocinar sobre os problemas que você tem que resolver.
125 |
126 | >"Eu tentei. Mas é muito complexo e tem péssima legibilidade."
127 |
128 | Tudo é difícil no começo. Eu tenho certeza que você ralou para aprender a programar e também para aprender POO. Provavelmente começar a fazer algo em POO foi mais fácil do que escrever seu primeiro programa. Principalmente porque você já estava familiarizado com alguns conceitos comuns, como declaração de variáveis e estruturas de repetição como *for*/*while*.
129 |
130 | Para começar com FP, é quase como começar a aprender a programar de novo (dependendo de qual linguagem você escolher, será definitivamente como aprender a programar do zero).
131 |
132 | Muitos podem argumentar que FP tem má legibilidade. Se você vem de um *background* imperativo, códigos funcionais irão parecer como uma linguagem criptografada. Não porque está realmente criptografado, mas porque você ainda não conhece os conceitos comuns. Uma vez que você dominar esses fundamentos, se tornará muito mais fácil de ler.
133 |
134 | Veja esse código a seguir, escrito em Haskell e JavaScript (usando estilo imperativo):
135 |
136 | ```haskell
137 | guess :: Int -> [Char]
138 | guess 7 = "Much 7 very wow."
139 | guess x = "Ooops, try again."
140 | ```
141 |
142 | ```js
143 | function guess(x){
144 | if(x == 7){
145 | return "Much 7 very wow."
146 | }
147 | else {
148 | return "Oops, try again."
149 | }
150 | }
151 | ```
152 |
153 | Esse é um programa muito simples que exibe uma mensagem de parabéns quando o usuário digita `7` e uma mensagem de erro para outros valores. Pode parecer magia negra como o Haskell faz isso em apenas 2 linhas de código (ignore a primeira linha por enquanto, é apenas "anotações de tipo"). Mas é muito simples depois que você entende *Pattern Matching* (que não é só implementado em linguagens FP, mas principalmente nelas).
154 |
155 | O que o Haskell está fazendo:
156 |
157 | Se o argumento da função `guess` for igual a `7`, retorna **"Much 7 very wow."** ou retorne **“Ooops, try again.”** para qualquer outro valor. E é exatamente o que o código JavaScript está fazendo, mas o Haskell está identificando através de um "padrão" provido pelo programador.
158 |
159 | Pode parecer que não vale a pena usar isso uma vez que você pode simplesmente usar um if/else. Mas isso é muito poderoso quando estamos trabalhando com estruturas de dados complexas.
160 |
161 | ```haskell
162 | plus1 :: [Int] -> [Int]
163 | plus1 [] = []
164 | plus1 (x:xs) = x + 1 : plus1 xs
165 |
166 | -- plus1 [0,1,2,3]
167 | -- > [1,2,3,4]
168 | ```
169 |
170 | No programa acima, **plus1** é uma função que recebe uma lista de Ints e e adiciona `1` para cada elemento da lista. Ele identifica o padrão de uma lista vazia `[]` (e retorna outra lista vazia, já que não há elementos para adicionar `1`) e quando ele identificar o padrão de uma lista com elementos: nomeia o primeiro elemento da lista como **x** e os elementos restantes como **xs**. Então, executa a soma e concatena com o retorno da chamada recursiva.
171 |
172 | Eu tenho certeza que você passaria por maus bocados tentando reescrever a função `plus1` usando estilo imperativo em duas linhas de código e ainda deixá-lo legível.
173 |
174 |
175 | ## Então, vamos começar
176 |
177 | Exite muito conteúdo por aí falando sobre Programação Funcional, mas alguns que você não pode perder são:
178 |
179 | * [Principles of Functional Programming in Scala](https://www.coursera.org/course/progfun)
180 |
181 | * [Introduction to Functional Programming](https://www.edx.org/course/introduction-functional-programming-delftx-fp101x) ([Contents](https://github.com/fptudelft/FP101x-Content))
182 | * [Paradigms of Computer Programming — Fundamentals](https://www.edx.org/course/paradigms-computer-programming-louvainx-louv1-1x#.VKXX2orF_rd)
183 |
184 | Infelizmente, eles costumam iniciar no fim do ano, mas você pode seguir o conteúdo e os videos que estão disponíveis no youtube.
185 |
186 | Por outro lado, se você prefere livros, eu recomendo fortemente esses a seguir:
187 |
188 | * [Structure and Interpretation of Computer Programs](https://mitpress.mit.edu/sicp/full-text/book/book.html)
189 |
190 | * [How to Design Programs](http://htdp.org/)
191 |
192 | * [Concepts, Techniques, and Models of Computer Programming](http://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262220695)
193 |
194 | Boa Sorte no seu novo ano Funcional! ☺
195 |
--------------------------------------------------------------------------------
/javascript/003-escopo-de-variavel-js-e-hoisting-explicado.md:
--------------------------------------------------------------------------------
1 | # Escopo e _Hoisting_ de Variáveis no JavaScript Explicados
2 |
3 | * **Artigo Original**: [JavaScript Variable Scope and Hoisting Explained](http://javascriptissexy.com/javascript-variable-scope-and-hoisting-explained/)
4 | * **Tradução**: [Eric Douglas](https://github.com/ericdouglas)
5 |
6 | Nesta postagem, iremos aprender sobre escopo e hoisting (hasteamento) de variáveis no JavaScript e tudo sobre as idiossincrasias (peculiaridades) de ambos.
7 |
8 | É imperativo que nós tenhamos entendimento de como o escopo e o hasteamento de variável funcionam no JavaScript, se quisermos entender bem o JS. Estes conceitos podem parecer óbvios, mas não são. Há algumas importantes sutilezas que nós devemos compreender, se realmente quisermos ser desenvolvedores JavaScript bem sucedidos.
9 |
10 | ##Escopo de Variáveis
11 |
12 | Um escopo de variável é o contexto no qual a variável existe. O escopo especifica de onde você pode acessar uma variável e se você tem acesso à variável naquele contexto.
13 |
14 | Variáveis têm ou um escopo local ou um escopo global.
15 |
16 | ##Variáveis Locais (Escopo Nível-de-Função)
17 |
18 | Ao contrário da maioria das linguagens de programação, o JavaScript não tem um escopo em nível-de-bloco (variáveis com o escopo envolto por chaves); como alternativa, no JavaScript temos escopo por nível-de-função. As variáveis declaradas dentro de uma função são variáveis locais, e são somente acessíveis por dentro dessa função ou por funções dentro dessa função. Veja a minha postagem de [Closures](https://github.com/cerebrobr/traduz-ai/blob/master/javascript/004-entenda-closures-no-javaScript-com-facilidade.md) para saber mais em como acessar variáveis em funções exteriores a partir de funções interiores.
19 |
20 | Demonstração de Escopo de Nível-de-Função
21 |
22 | ```javascript
23 | var name = "Richard";
24 |
25 | function showName() {
26 | var name = "Jack"; // variável local; somente acessível na função showName
27 | console.log(name); // Jack
28 | }
29 |
30 | console.log(name); // Richard: a variável global
31 | ```
32 |
33 | Sem Escopo de Nível-de-Bloco
34 |
35 | ```javascript
36 | var name = "Richard";
37 | // O bloco nesta condicional if não cria um contexto local para a variável name
38 | if (name) {
39 | name = "Jack"; // este name é a variável global name e está sendo alterada para "Jack" aqui
40 | console.log(name); // Jack: ainda como a variável global
41 | }
42 |
43 | // Aqui, a variável name é a mesma variável global name, mas ela foi modificada na condicional if
44 | console.log(name); // Jack
45 | ```
46 |
47 | ### Se você não declarar as suas variáveis locais, encrenca está perto
48 |
49 | Sempre declare suas variáveis locais antes de usá-las. Aliás, você deveria usar o [JSHint](http://www.jshint.com/) para verificar seu código por erros de sintaxe e guias de estilo. Aqui está o problema ao não declarar variáveis locais:
50 |
51 | ```javascript
52 | // Se você não declarar suas variáveis locais com a palavra-chave var,
53 | // elas se tornam parte do escopo global
54 | var name = "Michael Jackson";
55 |
56 | function showCelebrityName() {
57 | console.log(name);
58 | }
59 |
60 | function showOrdinaryPersonName() {
61 | // Note a ausência da palavra-chave var,
62 | // tornando esta variável global:
63 | name = "Johnny Evers";
64 | console.log(name);
65 | }
66 |
67 | showCelebrityName(); // Michael Jackson
68 |
69 | // name não é uma variável local, ele simplesmente muda a variável global name
70 | showOrdinaryPersonName(); // Johnny Evers
71 |
72 | // A variável global é agora Johnny Evers, não mais o name da celebridade Michael Jackson
73 | showCelebrityName(); // Johnny Evers
74 |
75 | // A solução é declarar sua variável local com a palavra-chave var
76 | function showOrdinaryPersonName() {
77 | // Agora name é sempre uma variável local
78 | // e não irá sobrescrever a variável global
79 | var name = "Johnny Evers";
80 | console.log(name);
81 | }
82 | ```
83 |
84 | ### Variáveis locais têm prioridade sobre variáveis globais nas funções
85 |
86 | Se você declarar uma variável global e uma variável local com o mesmo nome, a variável local terá prioridade quando você tentar usá-la dentro de uma função (escopo local):
87 |
88 | ```javascript
89 | var name = "Paul";
90 |
91 | function users() {
92 | // Aqui, a variável name é local
93 | // e prevalece sobre a mesma variável name no escopo global
94 | var name = "Jack";
95 |
96 | // A busca por name começa bem aqui dentro da função
97 | // antes de tentar enxergar fora da função no escopo global
98 | console.log(name);
99 | }
100 |
101 | users(); // Jack
102 | ```
103 |
104 | ## Variáveis Globais
105 |
106 | Todas as variáveis declaradas fora de uma função estão no escopo global. No navegador, que é onde estamos interessados como desenvolvedores front-end, o contexto ou escopo global é o objeto _window_ (ou o documento HTML inteiro).
107 |
108 | - Qualquer variável declarada ou inicializada fora de uma função é uma variável global, e estará portanto disponível para toda a aplicação. Por exemplo:
109 |
110 | ```javascript
111 | // Para declarar uma variável global, você pode utilizar quaisquer das seguintes estratégias:
112 | var myName = "Richard";
113 |
114 | // ou mesmo
115 | firstName = "Richard";
116 |
117 | // ou
118 | var name;
119 | name;
120 | ```
121 |
122 | É importante notar que todas as variáveis globais são anexadas no objeto _window_. Então, todas as variáveis globais que nós declaramos podem ser acessadas pelo object _window_ como assim:
123 |
124 | ```javascript
125 | console.log(window.myName); // Richard;
126 |
127 | // ou
128 | console.log("myName" in window); // true
129 | console.log("firstName" in window); // true
130 | ```
131 |
132 | - Se uma variável é inicializada (atribuída com um valor) sem primeiro ser declarada com a palavra-chave var, ela é automaticamente adicionada ao contexto global, sendo deste modo uma variável global:
133 |
134 | ```javascript
135 | function showAge() {
136 | // age é uma variável global porque ela não foi declarada
137 | // com a palavra-chave var dentro da função:
138 | age = 90;
139 | console.log(age);
140 | }
141 |
142 | // age está no contexto global, portanto está disponível aqui também:
143 | console.log(age); // 90
144 | ```
145 |
146 | Demonstração de variáveis que estão no Escopo Global mesmo que pareça o contrário:
147 |
148 | ```javascript
149 | // Ambas variáveis firstName estão no escopo global,
150 | // mesmo embora a segunda esteja envolta pelo bloco {}:
151 | var firstName = "Richard";
152 | {
153 | var firstName = "Bob";
154 | }
155 |
156 | // Para reiterar: JavaScript não tem escopo por nível-de-bloco
157 |
158 | // A segunda declaração de firstName simplesmente redeclara e sobrescreve a primeira
159 | console.log(firstName); // Bob
160 | ```
161 |
162 | Outro exemplo:
163 |
164 | ```javascript
165 | for (var i = 1; i <= 10; ++i) {
166 | console.log(i); // imprime 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
167 | }
168 |
169 | // A variável i é uma variável global e está acessível
170 | // na seguinte função com o último valor que foi-lhe atribuído acima
171 | function aNumber() {
172 | console.log(i);
173 | }
174 |
175 | // A variável i na função aNumber abaixo é a variável global i que foi alterada no laço acima.
176 | // Seu último valor foi 11, atribuído um momento antes da saída do laço:
177 | aNumber(); // 11
178 | ```
179 |
180 | ### Variáveis de setTimeout são Executadas no Escopo Global
181 | Note que todas as funções no setTimeout são executadas no escopo global. Isto é ligeiramente complicado; considere isto:
182 |
183 | ```javascript
184 | // O uso do objeto "this" dentro da função setTimeout refere-se ao objeto Window, não ao myObj
185 |
186 | var highValue = 200;
187 | var constantVal = 2;
188 | var myObj = {
189 | highValue: 20,
190 | constantVal: 5,
191 | calculateIt: function () {
192 | setTimeout (function () {
193 | console.log(this.constantVal * this.highValue);
194 | }, 2000);
195 | }
196 | };
197 |
198 | // O objeto "this" na função setTimeout usou as variáveis globais highValue e constantVal,
199 | // porque a referência ao "this" na função setTimeout refere-se ao objeto global window,
200 | // não ao objeto myObj como anteciparíamos.
201 |
202 | myObj.calculateIt(); // 400
203 |
204 | // Este é um ponto importante a ser lembrado!
205 | ```
206 |
207 | ### Não Polua o Escopo Global
208 |
209 | Se você quer se tornar um mestre em JavaScript, o que certamente você quer ser (caso contrário você estaria assistindo 'Honey Boo Boo' neste exato momento), você tem que saber que é importante evitar criar muitas variáveis no escopo global, tal como este:
210 |
211 | ```javascript
212 | // Estas duas variáveis estão no escopo global e elas não deveriam estar aqui:
213 | var firstName, lastName;
214 |
215 | function fullName() {
216 | console.log("Full name: " + firstName + " " + lastName);
217 | }
218 | ```
219 |
220 | Este é o código melhorado e a maneira apropriada de se evitar poluir o escopo global:
221 |
222 | ```javascript
223 | // Declare as variáveis dentro da função onde serão variáveis locais:
224 | function fullName() {
225 | var firstName = "Michael", lastName = "Jackson";
226 |
227 | console.log("Full Name: " + firstName + " " + lastName);
228 | }
229 | ```
230 |
231 | Neste último exemplo, a função fullName está no escopo global.
232 |
233 | ## Hasteamento de Variáveis (Variable Hoisting)
234 |
235 | Todas declarações de variáveis são hasteadas (erguidas e declaradas) ao topo da função se definida dentro duma função; ou no topo do contexto global se definida fora duma função.
236 |
237 | É importante saber que somente declarações de variáveis são hasteadas ao topo, não a inicialização ou as atribuições (quando para uma variável é atribuído um valor) de variáveis.
238 |
239 | Exemplo de Hasteamento de Variável:
240 |
241 | ```javascript
242 | function showName() {
243 | console.log("First Name: " + name);
244 | var name = "Ford";
245 | console.log("Last Name: " + name);
246 | }
247 |
248 | showName ();
249 | // First Name: undefined
250 | // Last Name: Ford
251 |
252 | // A razão para a primeira impressão ser undefined é que a variável local name foi hasteada ao topo da função
253 | // Que significa que é esta a variável local que é chamada na primeira vez.
254 | // Veja como o código realmente é processado pela engine (motor) JavaScript
255 |
256 | function showName() {
257 | // name é hasteada (note que está indefinida (undefined) até este ponto,
258 | // já que a atribuição acontece depois mais abaixo):
259 | var name;
260 | console.log("First Name: " + name); // First Name: undefined
261 |
262 | name = "Ford"; // é atribuído um valor a name
263 |
264 | // Agora name é Ford
265 | console.log("Last Name: " + name); // Last Name: Ford
266 | }
267 | ```
268 |
269 | ### Declaração de Função Sobrescreve Declaração de Variável Quando Hasteada
270 |
271 | Ambas declarações de funções e variáveis são hasteadas para o topo do escopo que as contém. E a declaração de função tem prioridade sobre declarações de variável (mas não sobre atribuição de variável). Como notado acima, atribuição de variável não é hasteada, e nem atribuição de função. Como um lembrete, isto é uma atribuição de função: `var myFunction = function () {};`.
272 | Aqui temos um exemplo básico para demonstração:
273 |
274 | ```javascript
275 | // Tanto a variável quanto a função são nomeadas de myName:
276 | var myName;
277 |
278 | function myName() {
279 | console.log("Rich");
280 | }
281 |
282 | // A declaração da função sobrescreve a variável myName:
283 | console.log(typeof myName); // function
284 | ```
285 |
286 | ```javascript
287 | // Mas neste exemplo, a atribuição da variável sobrescreve a declaração da função
288 |
289 | // Isso é a atribuição de variável (inicialização) que sobrescreve a declaração da função:
290 | var myName = "Richard";
291 |
292 | function myName() {
293 | console.log("Rich");
294 | }
295 |
296 | console.log(typeof myName); // string
297 | ```
298 |
299 | É importante notar que as expressões função, tais como o exemplo abaixo, não são hasteadas:
300 |
301 | ```javascript
302 | var myName = function() {
303 | console.log("Rich");
304 | };
305 | ```
306 |
307 | No modo estrito (`"strict mode";`), um erro ocorrerá se você atribuir a uma variável algum valor sem primeiro declarar a variável. Sempre declare as suas variáveis!
308 |
309 | Sê bom. Durma bem. E curta programar!
310 |
--------------------------------------------------------------------------------
/series/voce-nao-precisa-de-jquery/02-manipulacao-dom.md:
--------------------------------------------------------------------------------
1 | # Manipulação do DOM
2 |
3 | * **Artigo original**: [DOM Manipulation](http://blog.garstasio.com/you-dont-need-jquery/dom-manipulation/)
4 | * **Tradução**: [Eric Cristhiano](https://github.com/ericcristhiano)
5 |
6 | Anteriormente, [aprendemos como selecionar elementos sem depender do jQuery](01-seletores.md), mas o que aprendemos sobre mudar elementos? Sobre criar novos elementos? Que tal mudar os elementos para outro lugar na página? Você pode ficar feliz em saber que tudo isso, e mais, também é possível sem utilizar o jQuery. A web API nos fornece todas as ferramentas que precisamos, mais uma vez.
7 | Você verá que algumas manipulações no DOM são triviais sem o auxílio do jQuery ou qualquer outra biblioteca. No entanto, outras podem ser um pouco mais complicadas. Este é um momento de destacar (novamente) que não estou tentando derrubar o jQuery, nem vou afirmar que é inútil ou completamente desnecessário. A intenção desses posts é para informa-lo como trabalhar com o navegador sem jQuery, se você preferir. Você pode concluir que, em muitos casos, uma biblioteca grande, como o jQuery, na maior parte não vai ser utilizada, e pode ser dispensada.
8 |
9 | 1. [Criando Elementos](#criando-elementos)
10 | 2. [Inserindo Elementos antes & depois](#inserindo-elementos-antes-e-depois)
11 | 3. [Inserindo elementos como filhos](#inserindo-elementos-como-filhos)
12 | 4. [Movendo elementos](#movendo-elementos)
13 | 5. [Removendo elementos](#removendo-elementos)
14 | 6. [Adicionando e removendo classes CSS](#adicionando-e-removendo-classes-css)
15 | 7. [Adicionando/removendo/alterando atributos](#adicionando-removendo-alterando-atributos)
16 | 8. [Adicionando e alterando conteúdo](#adicionando-e-alterando-conteudo)
17 | 9. [Adicionando/atualizando estilo dos elementos](#adicionando-atualizando-estilo-dos-elementos)
18 | 10. [Micro-bibliotecas para ajuda](#micro-bibliotecas-para-ajuda)
19 | 11. [Próximo](#proximo)
20 |
21 | ## Criando Elementos
22 |
23 | *jQuery*
24 |
25 | ```
26 | $('');
27 | ```
28 |
29 | *DOM API*
30 |
31 | ```
32 | // IE 5.5+
33 | document.createElement('div');
34 | ```
35 |
36 | Wow, isso foi muito fácil. O jQuery nos poupou algumas teclas, mas isso dificilmente vale o tamanho da biblioteca.
37 |
38 | ## Inserindo elementos antes e depois
39 |
40 | Vamos criar um elemento e inseri-lo após o outro elemento específico.
41 | Então, vamos começar com:
42 |
43 | ```
44 |
45 |
46 |
47 | ```
48 |
49 | E nós gostaríamos de criar um novo elemento com um ID '1.1' e inseri-lo entre as duas primeiras divs, dando-nos isto:
50 |
51 | ```
52 |
53 |
54 |
55 |
56 | ```
57 |
58 | *jQuery*
59 |
60 | ```
61 | $('#1').after('');
62 | ```
63 |
64 | *DOM API*
65 |
66 | ```
67 | // IE 4+
68 | document.getElementById('1')
69 | .insertAdjacentHTML('afterend', '');
70 | ```
71 |
72 | Há! Tome ISSO jQuery! Muito fácil em todos os navegadores apenas contanto com as ferramentas incorporadas no browser.
73 |
74 | Ok, mas e se quisermos inserir um novo elemento ANTES da primeira div, dando-nos isso:
75 |
76 | ```
77 |
78 |
79 |
80 |
81 | ```
82 |
83 | *jQuery*
84 |
85 | ```
86 | $('#1').before('');
87 | ```
88 |
89 | *DOM API*
90 |
91 | ```
92 | // IE 4+
93 | document.getElementById('1')
94 | .insertAdjacentHTML('beforebegin', '');
95 | ```
96 |
97 | Praticamente igual ao último, com a exceção de uma chamada de método diferente para jQuery e um diferente parâmetro para a abordagem JavaScript puro.
98 |
99 | ## Inserindo elementos como filhos
100 |
101 | Vamos dizer que temos isso:
102 |
103 | ```
104 | {description}
' + 277 | 'Twas brillig…' 91 | }; 92 | } 93 | } 94 | }; 95 | 96 | assert.equal(getHTML('jabberwocky'), '
Twas brillig…');
97 | //=> test passes
98 | ```
99 |
100 | Escrever esse *stub* pode parecer um pouco trabalhoso, mas agora podemos testar essa função sem precisar de um navegador. Se quisermos, podemos rodar isso na linha de comando sem um navegador *headless*. E como um bônus, o teste vai rodar muito, muito mais rápido do que um que tenha o objeto `document` inteiro.
101 |
102 | Uma outra forma de ter uma função pura é retornar outra função que eventualmente irá fazer algo impuro quando a chamarmos. Isso inicialmente parece um truque sujo, mas é totalmente legítimo. Por exemplo:
103 |
104 | ```js
105 | var htmlGetter = function(id) {
106 | return function() {
107 | var el = document.getElementById(id);
108 | return el.innerHTML;
109 | }
110 | }
111 | ```
112 |
113 | A função `htmlGetter` é pura porque rodando-a não acessamos uma variável global - ao invés disso, ela sempre retorna exatamente a mesma função.
114 |
115 | Fazer coisas dessa forma não é muito útil para testes unitários, e isso não remove a impureza completamente - apenas a posterga. E isso não é necessariamente uma coisa ruim. Lembre-se, queremos lidar com toda a lógica previamente nas funções puras e depois puxar o gatilho em quaisquer efeitos colaterais.
116 |
117 | ### *Pointfree* (sem pontos)
118 | Programação *Pointfree* ou programação *tácita* é um estilo particular de programação que funções de ordem superior como `curry` e `compose` tornam possível. Para explicar isso, vamos olhar novamente para o exemplo do poema do último artigo:
119 |
120 | > **Nota do tradutor:** Programação tácita, também chamada estilo **point-free** (sem pontos), é um paradigma de programação em que definições de função não identificam os argumentos (ou "pontos") em que elas operam. Ao invés disso, as definições meramente compõem outras funções, onde essas são combinadores que manipulam os argumentos. [Fonte](https://en.wikipedia.org/wiki/Tacit_programming).
121 |
122 | ```js
123 | var poem = 'Twas brillig, and the slithy toves\n' +
124 | 'Did gyre and gimble in the wabe;\n' +
125 | 'All mimsy were the borogoves,\n' +
126 | 'And the mome raths outgrabe.';
127 |
128 | var replace = curry(function(find, replacement, str) {
129 | var regex = new RegExp(find, 'g');
130 | return str.replace(regex, replacement);
131 | });
132 |
133 | var wrapWith = curry(function(tag, str) {
134 | return '<' + tag + '>' + str + '' + tag + '>';
135 | });
136 |
137 | var addBreaks = replace('\n', '
\n');
138 | var replaceBrillig = replace('brillig', wrapWith('em', 'four o’clock in the afternoon'));
139 | var wrapP = wrapWith('p');
140 | var wrapBlockquote = wrapWith('blockquote');
141 |
142 | var modifyPoem = compose(wrapBlockquote, wrapP, addBreaks, replaceBrillig);
143 | ```
144 |
145 | Note que `compose` espera que cada função passada receba exatamente um parâmetro. Então, usamos 'curry' para mudar nossas funções multi-parâmetros `replace` e `wrapWith` em funções de um único parâmetro. Note também que fomos um pouco criteriosos com a ordem de nossas funções, então `wrapWith`, por exemplo, recebe a *tag* como seu primeiro parâmetro ao invés do texto para ser envolvido. Se formos cuidadosos dessa forma na maneira como configuramos nossas funções, isso fará a criação de funções por composição fácil.
146 |
147 | > **Nota do autor**: A maioria das bibliotecas funcionais (como [Ramda](http://ramdajs.com/)), também incluem utilitários para trabalhar com funções que não tem seus parâmetros em uma ordem conveniente.
148 |
149 | Isso se torna tão fácil que você pode escrever *todo* o seu código dessa maneira. Mas note um pequeno efeito colateral: quando definimos a função `modifyPoem` final, nós nunca mencionamos em nenhum lugar que ela recebe um único argumento *string*. E se você olhar para as funções *curried*, `addBreaks`, `replaceBrillig`, `wrapP` e `wrapBlockquote`, nenhuma delas mencionam que recebem também apenas uma simples variável *string*. Isso é programação *pointfree* (sem pontos): começar com um conjunto base de funções utilitárias (como Ramda ou functional.js) e escrever seu código de uma forma que você nunca vai mencionar as variáveis de entrada.
150 |
151 | O que isso nos dá? Bom, nada de especial em relação ao próprio código. A coisa inteligente sobre o estilo sem pontos é que ele te força a usar `compose`, `curry`, `pipe`, etc. Por sua vez, isso *encoraja fortemente* que você mantenha funções pequenas e simples reunidas de maneira sensata. Em outras palavras, isso é uma limitação autoimposta, como um *haiku* ou um soneto. Nem toda poesia tem que ser escrita dessa forma - e seguir todas as regras não garante um belo poema - mas algumas poesias escritas nesses estilos podem ser incrivelmente belas.
152 |
153 | Fazer tudo no estilo sem pontos não é sempre prático. Algumas vezes, isso adiciona complicações desnecessárias em uma função simples. Mas dar uma chance e *tentar* escrever todas as suas funções sem pontos é uma boa maneira de entender melhor a programação funcional.
154 |
155 | ### Assinatura de Tipos de Hindley-Milner
156 | Uma vez que você esteja fazendo tudo "sem pontos" (*pointfree*), isso deixa uma dúvida, como comunicar outros programadores qual tipo de parâmetro eles devem passar para sua função. Para facilitar isso, programadores funcionais desenvolveram uma notação especial para especificar quais tipos de parâmetro uma função recebe, e o que ela retorna. A notação é chamada *assinatura de tipos de Hindley-Milner*. Nós a escrevemos como comentários onde definimos a função. Vamos ver alguns exemplos:
157 |
158 | ```js
159 | // instruction :: String -> String
160 | var instruction = function(verb) {
161 | return verb + ' me';
162 | }
163 | ```
164 |
165 | A assinatura de tipo diz que `instruction` recebe uma *String* como entrada e retorna outra *String*. Por enquanto, tudo bem. E se tivermos uma função que recebe dois parâmetros?
166 |
167 | ```js
168 | // wrapWith :: String -> (String -> String)
169 | var wrapWith = curry(function(tag, str) {
170 | return '<' + tag + '>' + str + '' + tag + '>';
171 | });
172 | ```
173 |
174 | Isso é um pouco mais complicado, mas não tão difícil. Essa notação diz que `wrapWith` recebe uma *String* e retorna uma *Função*, e essa função recebe uma *String* e retorna uma *String*. Note que isso funciona porque nós aplicamos *curry* na função. Quando estivermos usando esse estilo, está assumido que você sempre vai usar *curry* em todas suas funções.
175 |
176 | E algo com três parâmetros ao invés de dois? Uma forma de escrever isso seria:
177 |
178 | ```js
179 | // replace :: String -> (String -> (String -> String))
180 | var replace = curry(function(find, replacement, str) {
181 | var regex = new RegExp(find, 'g');
182 | return str.replace(regex, replacement);
183 | });
184 | ```
185 |
186 | Agora temos uma função que retorna uma função que retorna uma função que retorna uma *string*. Isso ainda faz sentido, mas porque sempre assumimos que tudo está sendo *curried*, tendemos a remover os parênteses:
187 |
188 | ```js
189 | // replace :: String -> String -> String -> String
190 | ```
191 |
192 | E se tivermos um parâmetro de um tipo diferente:
193 |
194 | ```js
195 | // formatDollars :: Number -> String
196 | var formatDollars = replace('${{number}}', '{{number}}');
197 |
198 | formatDollars(100);
199 | //=> $100
200 | ```
201 |
202 | Aqui temos uma função sem pontos (*pointfree*), e se torna claro porque as assinaturas de tipos são úteis. Essa pega um número e retorna uma *string*. E se tivéssemos um array?
203 |
204 | ```js
205 | // sum :: [Number] -> Number
206 | var sum = reduce(add, 0);
207 | ```
208 |
209 | Essa recebe um array de números e retorna um número (assumindo que aplicamos *curry* na função `reduce` do segundo artigo).
210 |
211 | Alguns exemplos finais:
212 |
213 | ```js
214 | // identity :: a -> a
215 | var identity = function(x) { return x };
216 |
217 | // map :: (a -> b) -> [a] -> [b]
218 | var map = curry(function(callback, array) {
219 | return array.map(callback);
220 | });
221 | ```
222 |
223 | A função `identity` acima recebe um parâmetro de um tipo e retorna uma variável do mesmo tipo. A função `map` por outro lado, recebe uma função que recebe uma variável do tipo *a* e retorna uma variável do tipo *b*. Depois então pega um array de valores, todos do tipo *a* e retorna um array de valores, todos do tipo *b*.
224 |
225 | Você verá que bibliotecas como [Ramda](http://ramdajs.com/), por exemplo, usam essa notação para documentar todas as funções da biblioteca.
226 |
227 | ### Indo Mais Fundo
228 | Nós mal arranhamos a superfície da programação funcional. Mas entendendo funções de primeira classe, aplicação parcial e composição nos dá os blocos básicos para irmos muito mais longe. Se você estiver interessado em ler mais, há uma lista de links úteis abaixo:
229 |
230 | - [Can Your Programming Language do This?](http://www.joelonsoftware.com/items/2006/08/01.html) by Joel Spolsky
231 | - [The Dao of Immutability](https://medium.com/javascript-scene/the-dao-of-immutability-9f91a70c88cd) by Eric Elliot
232 | - [Why Ramda?](http://fr.umio.us/why-ramda/), by Scott Sauyet
233 | - [Professor Frisby’s Mostly Adequate Guide to Functional Programming](https://github.com/MostlyAdequate/mostly-adequate-guide) by Brian Lonsdorf
234 | - [JavaScript Allongé](https://leanpub.com/javascriptallongesix/read) by Reg “raganwald” Braithwaite
235 |
--------------------------------------------------------------------------------
/series/entao-voce-quer-ser-um-programador-funcional/parte-1.md:
--------------------------------------------------------------------------------
1 | # Então você quer ser um Programador Funcional? (Parte 1)
2 |
3 | * **Artigo original**: [So You Want to be a Functional Programmer (Part 1)](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-1-1f15e387e536#.es7crd8y1)
4 | * **Tradução**: [Gabriel](https://github.com/gabriel-ribeiro-ir)
5 |
6 | Dar o primeiro passo para entender os conceitos de Programação Funcional é o mais importante e algumas vezes o passo mais díficil. Mas isto não tem de ser assim. Não com a perspectiva correta.
7 |
8 | ### Aprendendo a dirigir
9 |
10 | Quando acabamos de aprender a dirigir, nós fazemos um grande esforço. Parecia fácil quando víamos outras pessoas dirigindo. Mas acaba se tornando mais difícil do que pensamos.
11 |
12 | Nós praticamos no carro de nossos pais e não nos aventuramos pela rodovia até dominarmos as ruas de nossa vizinhança.
13 |
14 | Mas através de muita prática e alguns momentos de pânico que nossos pais gostariam de esquecer, nós aprendemos a dirigir e finalmente pegamos nossa habilitação.
15 |
16 | Com a habilitação em mãos, pegamos o carro em qualquer oportunidade que temos. Com cada viagem, nós melhoramos e nossa confiança aumenta. Então chega o dia em que temos que dirigir o carro de outra pessoa, ou o nosso finalmente entregou os pontos e temos que comprar um novo.
17 |
18 | Como foi aquela primeira vez atrás do volante de um **carro diferente**? Foi como a primeiríssima vez? Nem chega perto. Na primeira vez foi tudo tão estranho. Nós já estivemos em um carro antes disso, mas somente como passageiros. Desta vez nós estamos no assento do motorista. Os únicos com todos os controles.
19 |
20 | Mas quando dirigimos nosso segundo carro, simplesmente nos perguntamos algumas coisas simples como, onde vai a chave, onde estão os faróis, como usamos a seta e como ajustamos os retrovisores.
21 |
22 | Depois disto, dirigimos suavemente. Mas por que desta vez foi tão fácil comparada à primeira?
23 |
24 | Porque o novo carro é muito parecido com o antigo. Ele tinha todas as coisas básicas que um carro precisa e eles estavam praticamente no mesmo lugar.
25 |
26 | Algumas coisas foram implementadas de forma diferente e talvez tivesse algumas funcionalidades adicionais, mas nós não as usamos na primeira, ou mesmo na segunda vez que dirigimos. Eventualmente, nós aprendemos todas as novas funcionalidades. Pelo menos aquelas que nos importam.
27 |
28 | Bem, aprender linguagens de programação é parecido com isto. A primeira é a mais difícil. Mas uma vez que você tenha uma em seu cinturão, as subsequentes são mais fáceis.
29 |
30 | Quando você começa a segunda linguagem, você pergunta coisas como, "Como eu crio um módulo? Como faço uma busca em um array? Quais são os parâmetros da função substring?"
31 |
32 | Você está confiante que pode aprender esta nova linguagem porque ela te lembra a antiga, talvez com algumas coisas novas que esperançosamente farão sua vida mais fácil.
33 |
34 | ### Sua primeira Nave Espacial
35 |
36 | Se você tem dirigido um carro sua vida toda ou uma dúzia de carros, imagine que você está prestes a estar atrás do volante de uma nave espacial.
37 |
38 | Se você estivesse indo voar em uma nave espacial, não poderia esperar que sua habilidade na estrada ajudasse muito. Você estaria começando do zero. (Afinal somos todos programadores. Nós contamos a partir do zero.)
39 |
40 | Você começaria seu treinamento com a expectativa de que as coisas são bastante diferentes no espaço e que voar nesta geringonça é muito diferente que dirigir no chão.
41 |
42 | A física não mudou. Somente a maneira que você navega dentro do mesmo Universo.
43 |
44 | E é a mesma coisa com aprender Programação Funcional. Você deve esperar que as coisas serão um pouco diferentes. E muito do que você sabe sobre programação **não** será traduzível.
45 |
46 | Programação é pensar e Programação Funcional te ensinará a pensar diferente. Tanto que você provavelmente nunca mais voltará a pensar da mesma maneira.
47 |
48 | ### Esqueça tudo o que você sabe
49 |
50 | As pessoas amam dizer esta frase, mas é um pouco verdade. **Aprender programação funcional é como começar do zero**. Não completamente, mas efetivamente. Existem muitos conceitos similares mas é melhor esperar que você vai ter de re-aprender tudo.
51 |
52 | Com a perspectiva correta você terá as expectativas certas, e com as expectativas certas você não desistirá quando as coisas ficarem difíceis.
53 |
54 | Existem todos os tipos de coisas que você está acostumado a fazer como programador que não poderá mais fazer em Programação Funcional.
55 |
56 | Assim como no seu carro, você costumava dar a ré para sair da garagem. Mas em uma nave espacial não existe marcha a ré. Agora você pode pensar, "O QUÊ? SEM MARCHA A RÉ?! COMO DIABOS EU DEVERIA DIRIGIR SEM MARCHA A RÉ?!"
57 |
58 | Bem, acontece que você não precisa de marcha a ré em uma nave espacial por causa de sua habilidade de manobrar em um espaço tridimensional. Uma vez que você entenda isto, você nunca mais sentirá falta da marcha a ré outra vez. De fato, algum dia, você vai pensar em quanto limitado o carro realmente era.
59 |
60 | > Aprender Programação Funcional leva um tempo. Então seja paciente.
61 |
62 | Então vamos sair do mundo frio da Programação Imperativa e vamos dar um mergulho suave na fonte quentinha da Programação Funcional.
63 |
64 | O que se segue nesta série de artigos são Conceitos de Programação Funcional que ajudarão você antes de mergulhar na sua primeira Linguagem Funcional. Ou se você já mergulhou, vai te ajudar a compreender.
65 |
66 | Por favor não corra. Tome seu tempo de leitura deste ponto em diante e não tenha pressa para entender os exemplos de código. Você pode até mesmo parar de ler depois de cada seção para aprofundar as ideias, e então voltar depois para terminar.
67 |
68 | O que realmente importa é que você **entenda**.
69 |
70 | ### Pureza
71 |
72 | Quando Programadores Funcionais falam de Pureza, eles estão se referindo a Funções Puras.
73 |
74 | Funções Puras são funções simples. Elas somente operam em seus parâmetros de entrada.
75 |
76 | Aqui está um exemplo de Função Pura com Javascript:
77 |
78 | var z = 10;
79 | function add(x, y) {
80 | return x + y;
81 | }
82 |
83 | Note que a função **add** NÃO toca na variável z. Ela não lê nem escreve na variável **z**. Ela somente lê **x** e **y**, seus parâmetros, e retorna o resultado da adição deles.
84 |
85 | Isto é uma função pura. Se a função **add** tivesse acesso a **z**, não seria mais pura.
86 |
87 | Aqui está outra função para considerar:
88 |
89 | function justTen() {
90 | return 10;
91 | }
92 |
93 | Se a função **justTen** é pura, então ela pode somente retornar uma constante. Correto?
94 |
95 | Pelo motivo de não passarmos parâmetros para ela. E uma vez que, para ser pura, ela não pode acessar nada que não seja seus parâmetros, a única coisa que ela pode retornar é uma constante.
96 |
97 | Uma vez que funções puras que não recebem parâmetros não fazem nada, elas não são muito úteis. Seria melhor se **justTen** fosse definida como uma constante.
98 |
99 | > As Funções Puras mais úteis recebem pelo menos um parâmetro
100 |
101 | Considere esta função:
102 |
103 | function addNoReturn(x, y) {
104 | var z = x + y;
105 | }
106 |
107 | Perceba como esta função não retorna nada. Ela adiciona **x** e **y** e guarda na variável **z** mas não a retorna.
108 |
109 | É uma funçao pura, já que lida somente com seus parâmetros. Ela faz a adição, mas não retornando seu resultado, é inútil.
110 |
111 | > Toda função pura precisa retornar alguma coisa para ser **útil**
112 |
113 | Vamos considerar a primeira funçao **add** novamente:
114 |
115 | function add(x, y) {
116 | return x + y;
117 | }
118 | console.log(add(1, 2)); // imprime 3
119 | console.log(add(1, 2)); // ainda imprime 3
120 | console.log(add(1, 2)); // SEMPRE vai imprimir 3
121 |
122 | Observe que **add(1, 2)** é sempre **3**. Não é uma grande surpresa, mas somente porque a função é pura. Se a função **add** usasse algum valor externo, então você **nunca** poderia prever seu comportamento.
123 |
124 | > Funções puras **sempre** produzem a mesma saída dados os mesmos parâmetros.
125 |
126 | Visto que funções puras não podem mudar variáveis externas, todas as funções a seguir são **impuras**:
127 |
128 | writeFile(fileName);
129 | updateDatabaseTable(sqlCmd);
130 | sendAjaxRequest(ajaxRequest);
131 | openSocket(ipAddress);
132 |
133 | Todas estas funções tem o que é chamado de **Side Effects** (Efeitos colaterais). Quando você as chama, elas alteram arquivos e tabelas de banco de dados, enviam dados para um servidor ou pedem ao SO por um socket. Elas fazem mais do que somente operar em seus parâmetros de entrada e retornar uma saída. Portanto, você *nunca* pode prever o que estas funções retornam.
134 |
135 | > Funções puras **não possuem** side effects.
136 |
137 | Em linguagens de programação imperativas como Javascript, Java, e C#, os Side Effects estão por toda a parte. Isto torna o debugging mais díficil porque uma variável pode ser alterada em **qualquer lugar** do seu programa. Então quando você tem um bug por causa de uma variável que mudou para o valor errado na hora errada, onde você procura? Por toda a parte? Isto não é bom.
138 |
139 | Neste ponto você provavelmente está pensando, "COMO DIABOS EU FAÇO QUALQUER COISA **SOMENTE** COM FUNÇÕES PURAS?!"
140 |
141 | Em Programação Funcional você não só escreve Funções Puras.
142 |
143 | Linguagens Funcionais não podem eliminar os Side Effects, elas só podem confiná-los. Desde que os programas tem de interagir com o mundo real, algumas partes precisam ser impuras. O objetivo é minimizar a quantidade de código impuro e segregá-lo do resto do seu programa.
144 |
145 | ### Imutabilidade
146 |
147 | Você se lembra de quando viu o seguinte trecho de código:
148 |
149 | var x = 1;
150 | x = x + 1;
151 |
152 | E quem quer que esteve te ensinando falou para você esquecer o que você aprendeu em matemática? Na matemática, **x** nunca pode ser igual a **x + 1**.
153 |
154 | Mas em Programação Imperativa, isto significa: Pegue o valor atual de **x** e adicione **1** a ele e guarde o resultado de volta no **x**.
155 |
156 | Bem, em Programação Funcional, **x = x + 1** é ilegal. Então você deve **relembrar** o que você **esqueceu** da matemática... mais ou menos isto.
157 |
158 | > **Não** existem variáveis em Programação Funcional.
159 |
160 | Valores guardados ainda são chamados de variáveis por causa da história mas eles são constantes, por exemplo: Uma vez que **x** ganha um valor, será seu valor pela vida toda.
161 |
162 | Não se preocupe, **x** é uma variável local, então sua vida será curta. Mas enquanto estiver viva, ela nunca muda.
163 |
164 | Aqui está um exemplo de variáveis consantes em Elm, uma Linguagem Funcional Pura para Desenvolvimento Web:
165 |
166 | addOneToSum y z =
167 | let
168 | x = 1
169 | in
170 | x + y + z
171 |
172 | Se você não está acostumado com a sintaxe ML-Style, permita-me explicar. **addOneToSum** é uma função que recebe 2 parâmetros, **y** e **z**.
173 |
174 | Dentro do bloco **let** é atribuido a **x** o valor **1**, isto é, seu valor será igual a **1** pelo resto de sua vida. Sua vida acaba quando a função é encerrada ou mais precisamente quando o bloco **let** é avaliado.
175 |
176 | Dentro do bloco **in**, o cálculo pode incluir valores definidos no bloco **let**, vide **x**. O resultado do cálculo **x + y + z** é retornado, ou mais precisamente, **1 + y + z** é retornado já que **x = 1**.
177 |
178 | Novamente eu posso te ouvir perguntando "COMO DIABOS EU SUPOSTAMENTE FARIA ALGUMA COISA SEM VARIÁVEIS?!"
179 |
180 | Vamos pensar em quando nós queremos modificar variáveis. No geral, existem 2 casos que vem em mente: mudanças multi-valores (ex. mudando um único valor de um objeto ou registro) e mudanças de valor único (ex. contadores de loop).
181 |
182 | Programação Funcional lida com mudanças de valores em um registro fazendo uma cópia do registro com os valores alterados. Isto é feito eficientemente sem ter de copiar todas as partes do registro, usando estruturas de dados que torna isso possível.
183 |
184 | Programação funcional resolve mudanças de valor único exatamente da mesma forma, fazendo uma cópia dele.
185 |
186 | Oh, sim e **não** possuindo loops.
187 |
188 | "O QUÊ? SEM VARIÁVEIS E AGORA SEM LOOPS?! EU TE ODEIO!!!"
189 |
190 | Calma. Não é que não podemos fazer loops (sem trocadilhos), é só que não existem construtores específicos de loop como **for, while, do, repeat**, etc.
191 |
192 | > Programação Funcional usa recursão para fazer looping.
193 |
194 | Aqui estão duas maneiras de fazer loops em Javascript:
195 |
196 | // construtor de loop simples
197 | var acc = 0;
198 | for (var i = 1; i <= 10; ++i)
199 | acc += i;
200 | console.log(acc); // imprime 55
201 |
202 | // sem construtor de loop ou variáveis (recursão)
203 | function sumRange(start, end, acc) {
204 | if (start > end)
205 | return acc;
206 | return sumRange(start + 1, end, acc + start)
207 | }
208 | console.log(sumRange(1, 10, 0)); // imprime 55
209 |
210 | Perceba que a recursão, a abordagem funcional, realiza o mesmo que um loop **for** chamando a si mesma com um *novo* start (**start + 1**) e um *novo* acumulador (**acc + start**). Ela não modifica os valores antigos Ao invés disso usa novos valores calculados a partir dos antigos.
211 |
212 | Infelizmente, isto é díficil de ver no Javascript, mesmo que você gaste um tempinho estudando, por duas razões. Primeiro, a sintaxe do Javascript é espalhafatosa e segundo, provavelmente você não está acostumado a pensar recursivamente.
213 |
214 | No Elm, isto fica mais fácil de ler e por consequência fácil de entender.
215 |
216 | sumRange start end acc =
217 | if start > end then
218 | acc
219 | else
220 | sumRange (start + 1) end (acc + start)
221 |
222 | Aqui está como é executado:
223 |
224 | sumRange 1 10 0 = -- sumRange (1 + 1) 10 (0 + 1)
225 | sumRange 2 10 1 = -- sumRange (2 + 1) 10 (1 + 2)
226 | sumRange 3 10 3 = -- sumRange (3 + 1) 10 (3 + 3)
227 | sumRange 4 10 6 = -- sumRange (4 + 1) 10 (6 + 4)
228 | sumRange 5 10 10 = -- sumRange (5 + 1) 10 (10 + 5)
229 | sumRange 6 10 15 = -- sumRange (6 + 1) 10 (15 + 6)
230 | sumRange 7 10 21 = -- sumRange (7 + 1) 10 (21 + 7)
231 | sumRange 8 10 28 = -- sumRange (8 + 1) 10 (28 + 8)
232 | sumRange 9 10 36 = -- sumRange (9 + 1) 10 (36 + 9)
233 | sumRange 10 10 45 = -- sumRange (10 + 1) 10 (45 + 10)
234 | sumRange 11 10 55 = -- 11 > 10 => 55
235 | 55
236 |
237 | Você provavelmente está pensando que os loops **for** são mais fáceis de entender. Enquanto isto é discutível e mais como uma questão de **familiaridade**, loops não recursivos requerem Mutabilidade, o que é ruim.
238 |
239 | Eu não expliquei os benefícios da Imutabilidade aqui mas veja a seção **Global Mutate State** em [Por quê Programadores Precisam de Limites](https://medium.com/@cscalfani/why-programmers-need-limits-3d96e1a0a6db#.awvlo8d5l) para aprender mais.
240 |
241 | Um benefício óbvio é que se você tem acesso a um valor em seu programa, você somente tem acesso a leitura, o que significa que ninguém mais pode alterar este valor. Mesmo você. Então sem mutações acidentais.
242 |
243 | Além disso, se seu programa é multi-thread, então nenhuma outra thread pode puxar seu tapete. Aquele valor é constante e se outra thread quer mudá-lo, terá que criar um novo valor a partir do antigo.
244 |
245 | De volta aos anos 90, eu escrevi uma Game Engine para o [Creature Crunch](https://www.youtube.com/watch?v=uIOYSjBRORM) e a maior fonte de bugs foram em problemas multithreading. Desejava conhecer sobre imutabilidade naquela época. Mas lá atrás eu estava mais preocupado com a diferença entre as velocidades 2x ou 4x de um CD-ROM na performance do jogo.
246 |
247 | > Imutabilidade cria código simples e seguro.
248 |
249 | ### Meu cérebro!!!
250 |
251 | Por enquanto chega.
252 |
253 | Nas próximas partes deste artigo, eu vou falar sobre Higher-order Functions, Functional Composition, Currying e mais.
254 |
255 | A seguir:
256 | [Parte 2](parte-2.md) (em português)
257 | [Parte 2](https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-2-7005682cec4a) (em inglês)
258 |
--------------------------------------------------------------------------------
/javascript/005-prototipos-javascript-em-uma-linguagem-simples.md:
--------------------------------------------------------------------------------
1 | # Protótipos Javascript em uma Linguagem Simples
2 |
3 | 
4 |
5 | * **Artigo Original**: [JavaScript Prototype in Plain Language](http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/)
6 | * **Tradução**: [Eric Douglas](https://github.com/ericdouglas)
7 |
8 | **Protótipo** é um conceito fundamental que todo desenvolvedor JavaScript deve entender, e este post tem o objetivo de explicar o `prototype` JavaScript em uma linguagem simples e detalhada. Se você não entender o `prototype` JavaScript depois de ler este post, por favor coloque suas dúvidas nos comentários abaixo, eu vou pessoalmente responder todas as questões.
9 |
10 | Para entender o `prototype` em JavaScript você deve entender os objetos JavaScript. Se você não está familiar com os objetos, você deve ler meu post [Objetos JavaScript em detalhe](https://github.com/eoop/traduz-ai/blob/master/javascript/002-objetos-js-em-detalhe.md#objetos-javascript-em-detalhe). Igualmente, saber que uma *propriedade* é uma simples variável definida dentro de uma função.
11 |
12 | Existem dois conceitos inter-relacionados com `prototype` no JavaScript:
13 |
14 | **01** . Primeiro, existe uma **propriedade `prototype`** em toda função JavaScript (ela é vazia por padrão), e você anexa propriedades e métodos a essa propriedade `prototype` quando você quer implementar herança. Note que esta propriedade `prototype` não é enumerável: ela não está acessível em um loop for/in. Mas o Firefox, e a maioria das versões do Safari e Chrome, tem uma "pseudo" propriedade `__proto__` (de forma alternativa) que lhe permite acessar uma propriedade `prototype` de um objeto. Você provavelmente nunca vai usar esta pseudo propriedade `__proto__`, mas sabe que ela existe e é simplesmente uma forma de acessar uma propriedade `prototype` de um objeto em alguns navegadores.
15 |
16 | A propriedade `prototype` é usada primariamente para herança: você adiciona métodos e propriedades dentro de uma propriedade `prototype` de uma função para tornar estes métodos e propriedades disponíveis para instâncias desta função.
17 |
18 | Aqui temos um exemplo simples de herança com a propriedade `prototype` (mais sobre herança depois):
19 |
20 | ```javascript
21 |
22 | function PrintStuff (myDocuments) {
23 | this.documents = myDocuments;
24 | }
25 |
26 | // Nós adicionamos o método print() para a propriedade prototype de PrintStuff
27 | // então outras instâncias (objetos) podem herdá-la
28 | PrintStuff.prototype.print = function () {
29 | console.log(this.documents);
30 | };
31 |
32 | // Cria um novo objeto com o construtor PrintStuff(), então permitindo
33 | // que este novo objeto de herde métodos e propriedades de PrintStuff
34 | var newObj = new PrintStuff("Eu sou um novo Objeto e eu posso imprimir.");
35 |
36 | // newObj herda todas as propriedades e métodos, incluindo o método print,
37 | // da função PrintStuff. Agora newObj pode chamar print diretamente, mesmo
38 | // nunca tendo criado um método print() nele.
39 | newObj.print(); // Eu sou um novo Objeto e eu posso imprimir.
40 |
41 | ```
42 |
43 | **02** . O segundo conceito com `prototype` no JavaScript é o **atributo `prototype`**. Pense no atributo `prototype` como uma característica do objeto; esta característica nos informa o objeto "pai". Em simples palavras: um atributo `prototype` de um objeto aponta para o objeto "pai" - o objeto do qual foram herdadas as propriedades. O atributo `prototype` é normalmente referenciado como *objeto prototype*, e ele é configurado automaticamente quando você cria um novo objeto. Esclarecendo sobre isso: todo objeto herda propriedades de algum outro objeto, e este outro objeto é a propriedade prototype ou "pai". (Você pode pensar sobre o **atributo prototype** como uma linhagem ou o "pai"). No código acima, o `prototype` de `newObj` é `PrintStuff.prototype`
44 |
45 | Nota: Todos os objetos têm atributos como propriedades de objetos têm atributos. E os atributos do objeto são: `prototype`, `class` e `extensible`. É este atributo `prototype` que vamos discutir neste segundo exemplo.
46 |
47 | Note também que a "pseudo" propriedade `__proto__` contém um objeto prototype (o objeto pai que ela herda seus métodos e propriedades).
48 |
49 | ## Uma nota importante
50 |
51 | **Construtor**
52 |
53 | Antes de continuarmos, vamos rapidamente examinar o construtor. Um **construtor** é uma função usada para inicializar novos objetos, e você usa a palavra `new` para chamar o construtor.
54 |
55 | Por exemplo:
56 |
57 | ```javascript
58 |
59 | function Account () {
60 |
61 | }
62 |
63 | // Este é o uso do construtor Account para criar
64 | // um objeto userAccount
65 | var userAccount = new Account();
66 |
67 | ```
68 |
69 | Além disso, todos objetos que herdam de outro objeto também herdam uma propriedade `constructor`. E esta propriedade `constructor` é simplismente uma propriedade (como qualquer variável) que detém nossa indicação ao construtor do objeto.
70 |
71 | ```javascript
72 |
73 | // O construtor neste exemplo é Object()
74 | var myObj = new Object();
75 |
76 | // e se depois você quiser encontrar o construtor de myObj
77 | console.log(myObj.constructor); // Object()
78 |
79 | // Outro exemplo: Account() é o construtor
80 | var userAccount = new Account();
81 |
82 | // Encontra o construtor do objeto userAccount
83 | console.log(userAccount.constructor); // Account()
84 |
85 | ```
86 |
87 | ## Atributo prototype de Objetos Criados com new Object() ou Objetos Literais
88 |
89 | Todos os objetos criados com objetos literais e com o construtor `Object` herdam de `Object.prototype`. Portanto, `Object.prototype` é o atributo `prototype` (ou o objeto prototype) de todos objetos criados com `new Object` ou com `{}`. `Object.prototype` não herda nenhum método ou propriedade de outro objeto.
90 |
91 | ```javascript
92 |
93 | // O objeto userAccount herda de Object e, como tal,
94 | // seu atributo prototype é Object.prototype
95 | var userAccount = new Object();
96 |
97 | // Este exemplo demonstra o uso de um objeto literal para criar o objeto userAccount;
98 | // O objeto userAccount herda de Object; entretanto, seu atributo prototype é
99 | // o Object.prototype como o objeto userAccount acima.
100 | var userAccount = { name: "Mike" };
101 |
102 | ```
103 |
104 | **Atributo Prototype de Objetos Criados com uma Função Construtora**
105 |
106 | Objetos criados com a palavra-chave `new` e qualquer outro construtor além do construtor `Object()`, pegam seu prototype da função construtora.
107 |
108 | Por exemplo:
109 |
110 | ```javascript
111 |
112 | function Account () {
113 |
114 | }
115 |
116 | var userAccount = new Account()
117 | // userAccount inicializa com o construtor Account()
118 | // e portanto seu atributo prototype (ou objeto prototype)
119 | // é Account.prototype
120 |
121 | ```
122 |
123 | Similarmente, qualquer array como `var myArray = new Array()`, pege seu prototype de `Array.prototype` e ele herda as propriedades de `Array.prototype`.
124 |
125 | Então, temos duas formas gerais que um atributo prototype de um objeto é configurado quando um objeto é criado:
126 |
127 | **1** . Se um objeto é criado com um objeto literal (`var newObj = {}`), ele herda as propriedades do `Object.prototype` e nós dizemos que seu objeto prototype (ou atributo prototype) é `Object.prototype`.
128 |
129 | **2** . Se um objeto é criado a partir de uma função construtora como `new Object()`, `new Fruit()` ou `new QualquerCoisa()`, ele herda do construtor `Object()`, `Fruit()`, `QualquerCoisa()`. Por exemplo, com uma função como `Fruit()`, cada vez que criarmos uma nova instância de Fruit (`var aFruit = new Fruit()`), o novo prototype da instância será atribuído ao prototype vindo do construtor Fruit, que é `Fruit.prototype`. Qualquer objeto que for criado com `new Array()` vai ter `Array.prototype` como seu prototype. Qualquer objeto criado com o construtor Object (`como var anObj = new Object()`) herda de `Object.prototype`.
130 |
131 | É importante conhecer que na ECMAScript 5, você pode criar objetos com um método `Object.create()` que permite que você configure novos `object.prototype` para os objetos. Nós vamos cobrir sobre ECMAScript em outro post.
132 |
133 | ## Por que Prototype é Importante e Quando ele é Usado?
134 |
135 | Estas são duas importantes maneiras em que o `prototype` é usado no JavaScript, como vimos acima:
136 |
137 | **1** . **Propriedade Prototype: Herança baseada em protótipos**
138 |
139 | O protótipo é importante no JavaScript porque o JavaScript não tem herança clássica baseada em Classes (como a maioria das linguagens orientadas a objeto têm), e portanto toda herança no JavaScript é possivelmente feita a partir da propriedade `prototype`. O JavaScript tem um mecanismo de herança baseado em protótipos. Herança é um paradigma de programação onde objetos (ou Classes em algumas linguagens) podem herdar propriedades e métodos de outros objetos (ou Classes). No JavaScript, você implementa herança com a propriedade `prototype`. Por exemplo, você pode criar uma função Fruit (um objeto, pois todas as funções no JavaScript são objetos) e adicionar propriedades e métodos na propriedade `prototype` de Fruit, e todas as instâncias da função Fruit vão herdar todas as propriedades e métodos de Fruit.
140 |
141 | Demonstração de herança no JavaScript:
142 |
143 | ```javascript
144 |
145 | function Plant() {
146 | this.country = "Mexico";
147 | this.isOrganic = true;
148 | }
149 |
150 | // Adicionando o método shoeNameAndColor a propriedade prototype de Plant
151 | Plant.prototype.showNameAndColor = function () {
152 | console.log("I am a " + this.name + " and my color is " + this.color);
153 | }
154 |
155 | // Adicionando o método amIOrganic a propriedade prototype de Plant
156 | Plant.prototype.amIOrganic = function () {
157 | if (this.isOrganic)
158 | console.log("I am organic, baby!");
159 | }
160 |
161 | function Fruit (fruitName, fruitColor) {
162 | this.name = fruitName;
163 | this.color = fruitColor;
164 | }
165 |
166 | // Configura o protótipo de Fruit para o construtor de Plant,
167 | // então herdando todos os métodos e propriedades de Plant.prototype
168 | Fruit.prototype = new Plant();
169 |
170 | // Cria um novo objeto, aBanana, com o construtor Fruit
171 | var aBanana = new Fruit("Banana", "Yellow");
172 |
173 | // Aqui, aBanana usa a propriedade name do objeto prototype aBanana,
174 | // que é Fruit.prototype:
175 | console.log(aBanana.name); // Banana
176 |
177 | // Usa o método showNameAndColor do objeto prototype Fruit,
178 | // que é Plant.prototype. O objeto aBanana herda todas as
179 | // propriedades e métodos de ambas funções Plant e Fruit.
180 | console.log(aBanana.showNameAndColor());
181 | // I am a Banana and my color is yellow
182 |
183 | ```
184 |
185 | Note que o método `showNameAndColor` foi herdado pelo objeto `aBanana` apesar de ter sido definido todo o caminho até a cadeia de protótipos do objeto Plant.prototype.
186 |
187 | De fato, qualquer objeto que usar o construtor `Fruit()` vai herdar todos os métodos e propriedades de `Fruit.prototype` e todos os métodos e propriedades do protótipo de Fruit, que é `Plant.prototype`. Esta é **a principal maneira que herança é implementada no JavaScript** e o papel essencial da cadeia de protótipos neste processo.
188 |
189 | Para uma cobertura mais aprofundada sobre Programação Orientada a Objetos no JavaScript, obtenha o livro de Nicholas Zakas [Principles of Object-Oriented Programming in JavaScript ](https://leanpub.com/oopinjavascript).
190 |
191 | **2** . **Atributo `prototype`: Acessando Propriedades nos Objetos**
192 |
193 | O protótipo também é importante para acessar propriedades e métodos de objetos. O **atributo `prototype`** (ou objeto prototype) de qualquer objeto é o objeto "pai" onde as propriedades herdadas foram originalmente definidas. Isto é vagamente análogo a forma que você pensa sobre o sobrenome de seu pai - ele é seu "protótipo pai". Se nós queremos encontrar de onde nosso sobrenome veio, nós devemos primeiro checar e ver se você o criou sozinho; se não, a busca será movida para o protótipo pai para ver se você herdou dele. Se não foi criado por ele, a busca continua pelo pai dele.
194 |
195 | Similarmente, se você quer acessar uma propriedade de um objeto, a busca pela propriedade começa diretamente no objeto. Se o *runtime* do JavaScript não conseguir encontrar a propriedade lá, ele então irá procurar pela propriedade no protótipo do objeto - o objeto que ele herdou suas propriedades.
196 |
197 | Se a propriedade não for encontrada no protótipo do objeto, a busca pela propriedade muda para o protótipo do protótipo do objeto (o pai do pai do objeto - o avô). E isto continua até que não tenha mais protótipos (sem mais bisavôs e sem mais linhagem a ser seguida). **Isso, em essência, é a cadeia de protótipos**: a cadeia de um protótipo de um objeto para seu protótipo do protótipo e por ai vai. O JavaScript usa esta cadeia de protótipos para verificar por propriedades e métodos de um objeto. Se a propriedade não existe em nenhum protótipo de objeto da sua cadeia prototípica, então a propriedade não existe e `undefined` é retornado.
198 |
199 | Esse mecanismo da cadeia de protótipos é essencialmente o mesmo conceito que discutimos acima com a herança baseada em protótipos, exceto que agora estamos focados especificamente em como o JavaScript acessa os métodos e propriedades dos objetos via o protótipo do objeto.
200 |
201 | Este exemplo demonstra a cadeia de protótipos de um objeto protótipo de um objeto:
202 |
203 | ```javascript
204 |
205 | var myFriends = {name: "Pete"};
206 |
207 | // Para encontrar a propriedade name abaixo, a busca vai
208 | // iniciar diretamente no objeto myFriends e vai imediatamente
209 | // a propriedade name porque nós definimos a propriedade name
210 | // no objeto myFriends. Isto pode ser pensado como uma cadeia
211 | // de protótipos com um link
212 | console.log(myFriends.name);
213 |
214 | // Neste exemplo, a busca pelo método toString()
215 | // vai também começar no objeto myFriends, mas por
216 | // nós nunca termos criado um método toString() no
217 | // objeto myFriends, o compilador vai então buscar
218 | // por isso no protótipo de myFriends (o objeto que
219 | // ele herdou suas propriedades)
220 |
221 | // E uma vez que todos objetos criados com o objeto
222 | // literal herdam de Object.prototype, o método toString()
223 | // vai ser encontrado em Object.prototype - veja a importante
224 | // nota abaixo para todas propriedades herdadas de Object.prototype
225 |
226 | myFriends.toString();
227 |
228 | ```
229 |
230 | ### Uma Nota Importante
231 |
232 | > **Propriedades herdadas de Object.prototype por todos os objetos**
233 | >
234 | > Todos objetos no JavaScript herdam propriedades e métodos de `Object.prototype`. Estas propriedades e métodos herdados são `constructor`, `hasOwnProperty()`, `isPrototypeOf()`, `propertyIsEnumerable()`, `toLocaleString()`, `toString()`, e `valueOf()`. O ECMAScript 5 também adiciona 4 métodos de acesso a `Object.prototype`.
235 |
236 | Aqui um outro exemplo de cadeia prototípica:
237 |
238 | ```javascript
239 |
240 | function People () {
241 | this.superstar = "Michael Jackson";
242 | }
243 |
244 | // Define a propriedade "athlete" no protótipo de People
245 | // então este "athlete" é acessível por todos os objetos
246 | // que usam o construtor People()
247 | People.prototype.athlete = "Tiger Woods";
248 |
249 | var famousPerson = new People();
250 | famousPerson.superstar = "Steve Jobs";
251 |
252 | // A busca a superstar vai primeiramente verificar pela
253 | // propriedade superstar no objeto famousPerson, e uma vez
254 | // definido lá, esta é a propriedade que vai ser usada.
255 | // Por causa que nós sobrescrevemos a propriedade
256 | // superstar de famousPerson diretamente, a busca NÃO
257 | // vai prosseguir acima na cadeia de protótipos.
258 | console.log(famousPerson.superstar); // Steve Jobs
259 |
260 | // Note que no ECMAScript 5 você pode definir uma propriedade
261 | // para ser somente lida, e neste caso você não pode
262 | // sobrescrevê-la como fizemos anteriormente
263 |
264 | // Isto vai mostrar a propriedade do protótipo de famousPerson
265 | // (People.prototype) desde que a propriedade athlete não
266 | // tenha sido definida no objeto famousPerson
267 | console.log(famousPerson.athlete); // Tiger Woods
268 |
269 | // Neste exemplo, a busca prossegue na cadeia prototípica
270 | // e encontra o método toString do Object.prototype, o mesmo
271 | // que o objeto Fruit herdou - todos os objetos herdam de
272 | // Object.prototype como mencionamos acima.
273 | console.log(famousPerson.toString()); // [object Object]
274 |
275 | ```
276 |
277 | Todos os construtores embutidos (`Array()`, `Number()`, `String()`, etc) foram criados a partir do construtor Object, e então `Object.prototype` é seus protótipos.
278 |
279 | **Informação Adicional**
280 |
281 | Para mais sobre Objetos JavaScript, leia o Capítulo 6 de JavaScript - O Guia Definitivo de David Flanagan.
282 |
--------------------------------------------------------------------------------
/javascript/007-um-mergulho-no-javascript-puro.md:
--------------------------------------------------------------------------------
1 | # Um Mergulho no JavaScript Puro - Viljami S.
2 |
3 | * **Artigo Original**: [A Dive Into Plain JavaScript](http://blog.adtile.me/2014/01/16/a-dive-into-plain-javascript/)
4 | * **Tradução**: [Lucas F. Costa](https://github.com/lucasfcosta)
5 |
6 | Ainda que eu tenha trabalhado por mais de uma década construindo os mais diversos websites, fazem apenas 3 anos que comecei a aprender mais sobre como trabalhar com JavaScript puro ao invés de sempre usar jQuery como ponto de partida. O fato de que atualmente estou aprendendo uma dúzia de coisas novas todo dia fez com que o trabalho no projeto Adtile's JavaScript SDK parecesse mais com a construção de um projeto de código aberto do que um "trabalho de verdade" e eu tenho que dizer: gostei muito disso.
7 |
8 | Hoje eu vou compartilhar algumas das coisas básicas que aprendi durante os últimos anos, as quais espero que também te ajudem a mergulhar no mundo do JavaScript puro, tornando mais fácil a decisão de usar ou não jQuery no seu próximo projeto.
9 |
10 | ## Melhora Progressiva
11 |
12 | Enquanto libraries como [jQuery](http://jquery.com/) te ajudam a esquecer a maior parte das inconsistências entre navegadores, você vai ficar realmente familiarizado com eles assim que começar a usar JavaScript puro para tudo. Para evitar escrever um código cheio de "hacks" para o navegador e código que apenas resolve problemas de incompatibilidade entre navegadores, eu recomendo construir uma experiência melhorada progressivamente, usando uma detecção de funcionalidades para atingir somente os navegadores mais modernos. Isso não significa que navegadores como o IE7 não verão nada, significa apenas que eles obtêm uma experiência mais básica, sem melhoras no JavaScript.
13 |
14 | ## Aqui Está Como Vamos Fazer Isso
15 |
16 | Nós temos um fragmento JavaScript separado chamado "feature.js" que contém todos os testes de funcionalidades. A verdadeira lista de testes é muito mais longa, nós vamos voltar a nos preocupar com isso um pouco mais tarde. Para cortar alguns dos navegadores mais antigos, nós usamos esses dois testes:
17 |
18 | ```js
19 | var feature = {
20 | addEventListener : !!window.addEventListener,
21 | querySelectorAll : !!document.querySelectorAll,
22 | };
23 | ```
24 |
25 | Depois, na parte principal da aplicação, nós iremos detectar se essas funcionalidades são suportadas usando a simples declaração "`if`" abaixo. Caso elas não sejam suportadas o navegador não irá executar nada deste código:
26 |
27 | ```js
28 | if (feature.addEventListener && feature.querySelectorAll) {
29 | this.init();
30 | }
31 | ```
32 |
33 | Esses dois testes confirmam que nós temos uma maneira nativa de usar seletores CSS em JavaScript (`querySelectorAll`), uma maneira de adicionar e remover elementos facilmente (`addEventListener`) e também confirma que os padrões suportados pelo navegador são melhores do que os presentes no IE8. Leia mais sobre essa técnica chamada "Cortando a mostarda" no [Blog da BBC](http://responsivenews.co.uk/post/18948466399/cutting-the-mustard).
34 |
35 | ##Suporte ao navegador
36 |
37 | Aqui está uma lista "rústica" dos navegadores que suportam as funcionalides que estamos testando e consequentemente irão executar nosso JavaScript:
38 |
39 | * IE9+
40 | * Firefox 3.5+
41 | * Opera 9+
42 | * Safari 4+
43 | * Chrome 1+
44 | * iPhone e iPad iOS1+
45 | * Telefones e Tablets Android 2.1+
46 | * Blackberry OS6+
47 | * Windows 7.5+
48 | * Firefox Mobile
49 | * Opera Mobile
50 |
51 | ##O Básico, a Maneira JavaScript Puro
52 |
53 | Vamos começar a ver como as funcionalidades mais básicas e frequentemente usadas funcionam em JavaScript puro comparadas ao jQuery. Para cada exemplo irei prover ambas as maneiras: com jQuery e usando JavaScript puro.
54 |
55 | ###Document Ready
56 |
57 | Com jQuery, muitos de vocês provavelmente estão acostumados a escrever o `document.ready` desta maneira:
58 |
59 | ```js
60 | $(document).ready(function() {
61 | // Code
62 | });
63 | ```
64 |
65 | Mas você sabia que você pode simplesmente colocar o seu JavaScript no final da página e ele vai fazer basicamente a mesma coisa? JavaScript também possui um *event listener* para o evento de quando o conteúdo DOM é carregado, sendo assim você também pode usar o código abaixo em vez do `document.ready` do jQuery:
66 |
67 | ```js
68 | document.addEventListener("DOMContentLoaded", function() {
69 | // Code
70 | }, false);
71 | ```
72 |
73 | ##API de Seletores
74 |
75 | A API de seletores nativos do JavaScript é muito boa. Ela funciona com seletores CSS e é muito similar à que o jQuery provê. Se você está acostumado à escrever isso em jQuery:
76 |
77 | ```js
78 | var element = $("div");
79 | ```
80 |
81 | Você agora pode substituir isso por:
82 |
83 | ```js
84 | var element = document.querySelector("div");
85 | ```
86 |
87 | Ou, para selecionar todos os `div`'s dentro de um determinado container:
88 |
89 | ```js
90 | var elements = document.querySelectorAll(".container div");
91 | ```
92 |
93 | Você também pode buscar por um elemento específico para encontrar seu respectivo filho:
94 |
95 | ```js
96 | var navigation = document.querySelector("nav");
97 | var links = navigation.querySelectorAll("a");
98 | ```
99 |
100 | Muito objetivo, fácil de entender e não requer, necessariamente, muito mais escrita, não é mesmo? Para ir um pouco além nós podemos até construir uma pequena *library* em JavaScript para que possamos fazer buscas no DOM de maneira mais simplificada. Aqui está uma ideia que Andrew Lunny teve:
101 |
102 | ```js
103 |
104 | // Isso nos dá uma simples função representada pelo símbolo de dólar e uma ligação com um evento na linha seguinte
105 | var $ = document.querySelectorAll.bind(document);
106 | Element.prototype.on = Element.prototype.addEventListener;
107 |
108 | // Assim é como você usa isso
109 | $(".element")[0].on("touchstart", handleTouch, false);
110 | ```
111 |
112 | ##Navegando pelo DOM
113 |
114 | Navegar pelo DOM com JavaScript puro é um pouco mais difícil do que com jQuery. Mas não é difícil demais. Aqui estão alguns exemplos simples:
115 |
116 | ```js
117 | // Obtendo o nó pai
118 | var parent = document.querySelector("div").parentNode;
119 |
120 | // Obtendo o nó de texto
121 | var next = document.querySelector("div").nextSibling;
122 |
123 | // Obtendo o nó anterior
124 | var next = document.querySelector("div").previousSibling;
125 |
126 | // Obtendo o primeiro elemento filho
127 | var child = document.querySelector("div").children[0];
128 |
129 | // Obtendo o último filho
130 | var last = document.querySelector("div").lastElementChild;
131 | ```
132 |
133 | ##Adicionando e Removendo Classes
134 |
135 | Com jQuery, adicionar, remover e checar se um elemento possui certas classes é muito simples. É um pouco mais complexo se usarmos JavaScript puro. Dar a um elemento uma classe chamada "foo" e substituir todas as classes atuais fica algo como:
136 |
137 | ```js
138 | // Selecione um elemento
139 | var element = document.querySelector(".alguma-classe");
140 |
141 | // Dê a classe "foo" ao elemento
142 | element.className = "foo";
143 | ```
144 |
145 | Adicionando uma classe sem substituir as classes atuais:
146 |
147 | ```js
148 | element.className += " foo";
149 | ```
150 |
151 | Removendo a classe "no-js" de um elemento html e substituindo-a por "js":
152 |
153 | ```js
154 |
155 |