63
JAVASCRIPT AVANÇADO Ricardo Cavalcanti [email protected]

Javascript avançado

Embed Size (px)

DESCRIPTION

Javacript Avançado: herança, closures, curry, bind, partes feias, partes ruins

Citation preview

Page 1: Javascript avançado

JAVASCRIPT AVANÇADORicardo Cavalcanti

[email protected]

Page 2: Javascript avançado

Algumas Ferramentas

“Firebug integrates with Firefox to put a wealth of web development tools at your fingertips while

you browse. You can edit, debug, and monitor CSS, HTML, and JavaScript live in any web page!”

http://getfirebug.com

Page 3: Javascript avançado

Prototype: introdução

Não é a biblioteca prototype.js Javascript usa protótipos no seu modelo

de objetos O que importa é o que o objeto faz, e não

de quem ele herda Uma função construtora seta seu

prototype no objetos que cria

Page 4: Javascript avançado

Prototype: a propriedade prototype

Todo objeto tem uma propriedade prototype

Ao tenta acessar uma propriedade inexistente, javascript busca a propriedade no prototype do objeto E no prototype do prototype...

Page 5: Javascript avançado

Prototype: aumentando prototypes

Ao incluir propriedades e funções ao prototype de um construtor, elas são incluidas nos objetos que o construtor produzvar cat = new Cat("Barsik");

Cat.prototype.animal = "cat";Cat.prototype >> {animal: "cat"}cat.animal >> "cat"Cat.prototype.seeADog = function() {

return "I'm "+this.name+". Sshhhhhhh!";}

cat.seeADog() >> "I'm Barsik. Sshhhhhhh!";

Page 6: Javascript avançado

Prototype: mudando o prototype

Mudanças no prototype afetam todas as instâncias

var cat = new Cat("Barsik");var cat2 = new Cat("Murzik");

Cat.prototype.animal = "cat";cat.animal >> "cat"cat2.animal >> "cat“

Cat.prototype.animal = "dog";cat.animal >> "dog"cat2.animal >> "dog"

Page 7: Javascript avançado

Prototype: propriedades

O objeto pode ter suas próprias propriedades A delegação cuida da prioridadefunction Gadget(/*String*/ name) {

this.name = name;}var iphone = new Gadget("iPhone");Gadget.prototype.name = "none";

iphone.name >> "iPhone"delete iphone.name;iphone.name >> "none"

Page 8: Javascript avançado

Prototype: estendendo JS Objects

Podemos estender inclusive os JS Objects

String.prototype.trim = function(){return this.replace(/^\s+|\s+$/g, '');

};

“ bla “.trim() >> “bla”

Page 9: Javascript avançado

HERANÇA

Page 10: Javascript avançado

Herança clássica

Objetos são instancias de classes

Classes herdam de outra classe

Page 11: Javascript avançado

Herança prototípica

Não há classes Objetos herdam de objetos Um objeto tem um link para outro objeto No Firefox é __proto__

var newObject = Object(oldObcet)

newObject

__proto__

oldObject

Page 12: Javascript avançado

Herança prototípica

var oldObject = { firstMethod: function(){...}, secondMethod: function(){...},};

var newObject = Object(oldObject);

newObject.thirdMethod = function(){...};

var anotherObject = Object(newObject);

anotherObject.thirdMethod();

Page 13: Javascript avançado

Herança prototípica

Ao acessar uma propriedade, o interpretador vai primeiro no objeto,

depois busca no protótipo do objeto, ...depois no protótipo do protótipo... Até Object.prototype

foo 2 foo 1

newObject oldObject

Page 14: Javascript avançado

Herança prototípica

Mudanças no oldObject serão visíveis no newObject, como já vimos

Mudanças no newObject não alteram o oldObject

foo 2 foo 1

newObject oldObject

Page 15: Javascript avançado

Herança pseudoclássica

Com herança prototípica pura, a linguagem deve ter um operador como a função Object Para criar novos objetos utilizando um já

existente

Javascript usa operadores aparentemente clássicos Mas que funcionam prototipicamente

Page 16: Javascript avançado

Pseudoclássica

Três mecanismos: Funções Contruturas O operador new O atributo prototype, nas funções

Page 17: Javascript avançado

Operador new

function Contructor(){ this.member = ...;}

Contructor.prototype.firstMethod = function(a,b) {...}

Contructor.prototype.secondMethod = function(a,b) {...}

var newObject = new Constructor();

Page 18: Javascript avançado

Operador new

new Constructor() retorno um novo objeto ligado ao Constructor.prototype

newObject Constructor.prototype

newObject oldObject

Page 19: Javascript avançado

Operador new

A função Contructor() pasa o novo objeto na variável this Para inicizar o novo objeto

newObject Constructor.prototype

Page 20: Javascript avançado

prototype

Cada objeto function criado tem um atributo prototype

O prototype tem um atributo constructor, que refencia o objeto function

Outros atributos adicionados no prototype da função serão vistos nos objetos constuídos com ela

É possível criar constantes e métodos par aos objetos

Page 21: Javascript avançado

Herança Pseudoclássica

É possível simular herança clássica atribuindo um objeto criado por um constutor como o protótipo de outra

Mas não é exatamente herança clássica

function BiggerConstructor(){};BiggerConstructor.prototype = new

MyContructor()

Page 22: Javascript avançado

function SuperClasse(){}

SuperClasse.prototype.hello = function(){alert('super hello')};

function SubClasse(){};SubClasse.prototype = new SuperClasse();SubClasse.prototype.subhello = function(){alert('sub hello')};

var o = new SubClasse();

o.hello();o.subhello();

Page 23: Javascript avançado

function SuperClasse(){}

SuperClasse.prototype.name = 'super';

SuperClasse.prototype.hello = function(){alert(this.name)};

function SubClasse(){

this.name = 'sub';

};

SubClasse.prototype = new SuperClasse();

SubClasse.prototype.subhello = function(){alert(this.name)};

var o = new SubClasse();

o.hello();

o.subhello();

Page 24: Javascript avançado

CLOSURES

Page 25: Javascript avançado

Escopo nas funções

O escopo é definido pelas funções, e não pelos blocos

Funções internas têm acesso às variáveis das funções externas Exceto this e argumentsfunction f (){ var y = 3; var g = function(){ var x = 2+ y; ... }}

E se a função interna durar mais que a função externa?

Page 26: Javascript avançado

Closures

Quando a função interna dura mais que a externa, o escopo externo é preservado Isso se chama closure

Page 27: Javascript avançado

Um closure simples

var f = function(x){ var m = function(y){ return x * y; } return m;}var dobro = f(2);var triplo = f(3);

alert(dobro(10));alert(triplo(10));

Quando f() é executado, um novo m() é criado

Enquanto m() existir, seu escopo existe, e o do seu ‘pai’ também

Page 28: Javascript avançado

Usando closures

Information Hiding Funções com timers Event handlers Callbacks

Page 29: Javascript avançado

Clojures: Dados privados

var quo = function (status) { return { get_status: function ( ) { return status; } };};

var myQuo = quo("amazed");alert(myQuo.get_status( ));

Page 30: Javascript avançado

Closures: timers

var fade = function (node) {

var level = 1;

var step = function ( ) {

var hex = level.toString(16);

node.style.backgroundColor = '#FFFF' + hex + hex;

if (level < 15) {

level += 1;

setTimeout(step, 100);

}

};

setTimeout(step, 100);

};

fade(document.body);

Page 31: Javascript avançado

Closure: event handler

Função que adiciona um event handler para uma lista de nodes. Ao clicar, alerta a ordem do nó.

var add_the_handlers = function (nodes) { var i; for (i = 0; i < nodes.length; i += 1) { nodes[i].onclick = function (e) { alert(i); } }}; Qual o resultado?

Page 32: Javascript avançado

Closure: event handler

Exemplo corretovar add_the_handlers = function (nodes) { var i; for (i = 0; i < nodes.length; i += 1) { nodes[i].onclick = function (i) { return function (e) { alert(i); }; } (i); }};

Page 33: Javascript avançado

CURRY

Page 34: Javascript avançado

Curry

Funções são valores É possível combinar uma função com

alguns argumentos e produzir outra funçãovar mult = function (a, b) {return a * b};var duplicar = mult.curry(2);var duplicar = function (b){ retunr 2*b};

Page 35: Javascript avançado

Função curry

Curry cria um closure que guarda a função original e seus argumentos para realizar o currying

Quando executada, ela retorna o resultado da função original com os argumentos passados ao curry e os passados a ela

var mult = function (a, b) {return a * b};var duplicar = mult.curry(2);var seis = duplicar(3); //mult.curry(2)(3) >>> 6

Page 36: Javascript avançado

Function.prototype.curry = function ( ) { var args = arguments, that = this; return function ( ) { return that.apply(null,

args.concat(arguments)); };}); //PROBLEMA: arguments não é um

array

Page 37: Javascript avançado

Função curry: final

Function.prototype.curry = function ( ) { var slice = Array.prototype.slice, args = slice.apply(arguments), that = this; return function ( ) { return that.apply(null,

args.concat(slice.apply(arguments))); };});

Page 38: Javascript avançado

Closures: callbacks

var replace = function (el, url){

var callback = function(t){ el.innerHTML = t; }; makeXHR(callback, url); // ajax}

replace (myEl, minhaURL);

Page 39: Javascript avançado

Closures : cuidados

Evite criar funções em loops Para evitar closures indesejados

Atenção com o this Mais sobre isso com bind

Page 40: Javascript avançado

BIND

Page 41: Javascript avançado

This

window.name = "the window object"

function scopeTest() { return this.name}

scopeTest()// -> "the window

object"

var foo = { name: "the foo

object!", otherScopeTest:

function() { return this.name }

}

foo.otherScopeTest()// -> "the foo object!"

Page 42: Javascript avançado

Javascript é dinâmica

//atribuindo a função, SEM executá-lawindow.test = foo.otherScopeTest

//chamando a funçãotest() ; // -> "the window object"

Page 43: Javascript avançado

Function bind

Eu gostaria de escolher o ‘this’ da minha funçãowindow.test = foo.otherScopeTest.bind(foo);test() // -> "the foo object!"

Function.prototype.bind = function(scope) { var _function = this; return function() { return _function.apply(scope, arguments); }}

Page 44: Javascript avançado

PARTES FEIASRicardo Cavalcanti

[email protected]

Page 45: Javascript avançado

Variáveis globais

Todas as coisas são carregadas no mesmo objeto global

var foo = value;window.foo = value;foo=value;

Page 46: Javascript avançado

Escopo

Apesar da sintaxe de C Blocos não criam escopo O escopo é sempre da função

Page 47: Javascript avançado

Inserção de ;

Há um mecanismo de completar com ; alguns comandos

return { status: true };

return { status: true };

return ;{ status: true };

=

Page 48: Javascript avançado

Palavras reservadas

abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with

var method; // okvar class; // illegalobject = {box: value}; // okobject = {case: value}; // illegalobject = {'case': value}; // okobject.box = value; // okobject.case = value; // illegalobject['case'] = value; // ok

Page 49: Javascript avançado

Unicode

char em Javascript tem 16bits

Um char unicode são 2 caracteres em javascript

Page 50: Javascript avançado

typeof

typeof 98.6 >> ‘number’

typeof null >> ‘object’

my_value === null //melhorif (my_value && typeof my_value === 'object') { // my_value is an object or an array! }

typeof /a/ >> ‘object’ ou ‘function’ depende da implementação

Page 51: Javascript avançado

parseInt

Converte um string num integer Para quando vê um não-dígito

parseInt("16") >> 16parseInt("16 mil") >> 16

Se o string começar com 0 é utilizada a base 8parseInt("08") >> 0parseInt("09") >> 0

Parse int pode receber a baseparseInt("08", 10) >> 8

Page 52: Javascript avançado

Ponto fllutuante

Javascript usa IEEE Standard for Binary Floating-Point Arithmetic (IEEE 754)

Portanto0.1 + 0.2 !== 0.3

Atenção quando utilizar valores monetários Melhor multiplicar por 100

Page 53: Javascript avançado

NaN

Se algum operando for NaN, o resultado da operação será NaN Converter um string em inteiro gera NaN

Porém NaN === NaN // false

Use a função isNaN isNaN(NaN) // true

Page 54: Javascript avançado

null e undefined

value = myObject[name]; if (value == null) { alert(name + ' not found.'); } Um erro anula o outro! value é undefined, mas o operador ==

faz o type coersion Cuidado: NaN e undefined são variáveis

globais!

Page 55: Javascript avançado

PARTES RUINS

Page 56: Javascript avançado

==

'' == '0' // false0 == '' // true0 == '0' // true

false == 'false' // falsefalse == '0' // true

false == undefined // falsefalse == null // falsenull == undefined // true

' \t\r\n ' == 0 // true

Page 57: Javascript avançado

with

Para acessar os atributos de um objeto Problemas:

with (obj) { a = b; }

O mesmo queif (obj.a === undefined) { a = obj.b === undefined ? b : obj.b;} else { obj.a = obj.b === undefined ? b : obj.b;}

Page 58: Javascript avançado

eval

Evite! Bem como outras formas que recebem

código como string Contrutor de Fuction setTimeout setInterval

Problema de segurança Difícil de checar e de ler

Page 59: Javascript avançado

switch Fall Through

Switch-case sem break Fonte de muitos erros, cuidado!

Page 60: Javascript avançado

Comandos sem bloco

Sempre use blocos nos comandos

if (ok) t = true;

if (ok) t = true; advance( );

if (ok) { t = true; advance( );}

if (ok) { t = true;}advance( );

vira

parece

Mas naverdade é

Page 61: Javascript avançado

Operadores de bits

Os mesmos de java& and| or^ xor~ not>> signed right shift>>> unsigned right shift<< left shift

Convertem para integer e desconvertem Longe do hardware, lentos

Page 62: Javascript avançado

Typed Wrappers

Desnecessáriosnew Boolean(false)

Evite o uso de new Boolean, new Number, new String

Também evite new Object e new Array Use {} e []

Page 63: Javascript avançado

Para evitar erros