Alguns assuntos extras para o treinamento de Javascript da Caelum
- Funções
- Array
- This - O contexto de execução
- Event Delegation
- JSON
- Mock HTTP
- Herança
- Node HTTP server
- Posts no blog
- Referências bibliográficas
- CORS
Funções podem ser declaradas de duas formas:
Function Declaration:
function foo() {
console.log("bar");
}
Function Expression:
var foo = function() {
console.log("bar");
}
A diferença entre as duas formas, é que a Function Declaration passa pelo mecaniso de hoisting, onde ela é "içada" para o topo do script:
var foo = function() {
console.log("bar");
}
function foo = function() {
console.log("qux");
}
foo(); //Imprime "bar"
Funções em JavaScript são objetos de primeira classe. Dessa forma, podemos gravar propriedades neles:
var foo = function() {
console.log("bar");
}
foo.qux = "John Doe";
console.log(foo.qux); //Imprime "John Doe"
Funções podem até mesmo ser criadas usando uma função construtora:
// A função foo recebe 2 parametros e retorna a soma deles
var foo = new Function("num1", "num2", "return num1 + num2;");
console.log( foo(2, 3) ); // Imprime 5;
Funções, então, são objetos que tem o "super poder" de serem invocadas
Alguns métodos úteis de array
var array = [3,5,4,6,2,7,9,1,0,8];
// Remove o último elemento e o retorna
console.log( array.pop() );
// Remove o primeiro elemento e o retorna
console.log( array.shift() );
// Adiciona um elemento no início e retorna o novo tamanho do array
console.log( array.unshift("foo") );
// Inverte a ordem dos elementos
console.log( array.reverse() );
Removendo um elemento do meio do array:
var array = [3,5,0];
var index = array.indexOf(5);
array.splice(index, 1);
console.log(array); // Imprime [3,0]
A função Array.prototype.indexOf foi criada na 5ª versão do ECMAscript, então não funciona no IE8-
Para saber mais, verifique a tabela de compatibilidade do ECMA 5
A palavra reservada this simboliza o contexto de execução no JavaScript:
var foo = {
bar: "qux",
baz: function() {
console.log(this.bar);
}
}
foo.baz(); // Imprime "qux"
O contexto de execução pode ser alterado:
var mamifero = {
animal: "mamífero",
dizAnimal: function() {
console.log( this.animal )
}
}
var gato = {
animal: "Gato"
}
var cachorro = {
animal: "cachorro"
}
mamifero.dizAnimal();
// Function.prototype.call altera o contexto de execução
mamifero.dizAnimal.call(gato);
mamifero.dizAnimal.call(cachorro);
A delegação de eventos é possível, porque os eventos se propagam pela hierarquia do DOM. Exemplo com JavaScript puro:
HTML
<ul>
<li>Item 1. Clique em mim!</li>
<li>Item 2. Clique em mim!</li>
</ul>
JavaScript
var ul = document.querySelector('ul');
ul.addEventListener('click', function(event) {
var target = event.target;
console.log( target.textContent );
});
Um JavaScript Object Notation, ou JSON, não é um objeto, mas apenas um texto que utiliza a mesma notação de objetos do JavaScript. Para criarmos um objeto a partir de um JSON, devemos parsea-lo:
var json = '{"foo": "bar", "baz": "qux"}';
var objeto = JSON.parse(json);
console.log(objeto.foo); // Imprime "bar"
console.log(objeto.baz); // Imprime "qux"
Podemos também transformar um objeto em um JSON:
var objeto = {nome: "John Doe"};
var json = JSON.stringify(objeto);
console.log(json); // Imprime "{"nome": "John Doe"}"
A maioria das bibliotecas e frameworks que trabalham com JSON ja fazem o parse automaticamente, retirando essa responsabilidade do desenvolvedor. É o caso do jQuery.fn.ajax e jQuery.fn.getJSON
Uma forma de testar funcionalidades ajax sem precisar subir um servidor, é usando um serviço de Mock. Um muito bom é o o Mocky.io, que suporta também jsonp
A herança em JavaScript é feita quando fazemos o protótipo de um objeto herdar outro objeto:
function Mamifero() {
this.anda = function() {
console.log(this.animal + " andando");
}
}
function Gato() {
this.animal = "Gato";
this.mia = function() {
console.log("Miau");
}
}
function Cachorro() {
this.animal = "Cachorro";
this.late = function() {
console.log("Au au");
}
}
console.log( Mamifero.prototype );
console.log( Gato.prototype );
console.log( Cachorro.prototype );
// Alterando os prototypes de Cachorro e Gato:
Cachorro.prototype = new Mamifero();
Gato.prototype = new Mamifero();
console.log( Gato.prototype );
console.log( Cachorro.prototype );
// Agora Gato e Cachorro também são Mamíferos. Logo, eles também tem a
// fução anda()
var tequila = new Gato();
var veludo = new Cachorro();
tequila.anda();
tequila.mia();
veludo.anda();
veludo.mia();
Nota: Tequila e Veludo são respectivamente minha gata e meu cachorro
Subir um pequeno servidor em NodeJS é muito simples:
var http = require('http');
var server = http.createServer(function(req, res) {
res.write('<h1> Ola! </h1>');
res.end();
});
server.listen(3000, function() {
console.log('Servidor rodando...');
});
CORS, ou Cross-Origin Resource Sharing, é uma alternativa ao JSONP, e funciona realizando um handshake entre a página e o outro servidor.
Esse handshake consiste de 2 headers: um na requisição e outro na resposta.
O header da requisição é um Origin
, que contém o dominio que está realizando a requisição:
Origin: http://jquery.com
O header da resposta é um Access-Control-Allow-Origin
, indicando que domínios podem acessar aquele recurso. Podemos usar um wildcard *
para liberar acesso público para qualquer domínio:
Access-Control-Allow-Origin: *
Podemos facilmente subir um servidor em NodeJS que usa o CORS para disponibilizar um recurso:
var http = require('http')
, obj = {foo: 'bar'}
, json = JSON.stringify(obj)
, porta = 3000;
var server = http.createServer(function(req, res) {
if (req.url = '/resource.json') {
res.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
res.write(json);
} else {
res.write('URL inválida');
}
res.end();
});
server.listen(porta, function() {
console.log('Servidor rodando na porta ' + porta);
});
Agora, a partir de um outro domínio, podemos fazer uma requisiçào AJAX para buscar o JSON que disponibilizamos:
$.ajax({
url: 'http://localhost:3000/resource.json',
success: function(data) {
console.log(data.foo);
};
});
Alguns posts relevantes sobre JavaScript no blog da Caelum:
- Reaproveitando código com JavaScript: herança e protótipos
- Conhecendo a stack MEAN: MongoDB, Express, Angular e Node.
- Organize seu código Javascript de maneira fácil!
- Automação de build de front-end com Grunt.js
- Experimente o Yeoman em seu workflow de projetos front-end
- Bye bye Grunt.js, hello Gulp.js!
- Não use jQuery no seu site mobile: conheça o Zepto.JS
- Logging, debugging e profiling de JavaScript com o Firebug
- Boas práticas com JavaScript e jQuery: código não-obstrusivo
- Conhecendo o operator new e os protótipos no JavaScript
- As múltiplas personalidades do this em JavaScript
- Entenda a nova especificação de classes do JavaScript Harmony ES6
- Pro JavaScript Techniques (RESIG, John)
- Secrets of the JavaScript Ninja (RESIG, John; BIBEAULT, Bear)
- O Melhor do JavaScript (CROCKFORD, Douglas)
- AngularJS (GREEN, Brad; SESHADRI Shyam)