desmistificando o javascript (alan silva)

Post on 15-Apr-2017

111 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Desmistificando JavaScript

Entendendo o lado mais mal-entendido da web

Plano de execução da engine

O foco será no funcionamento do V8.

LexerTokens

ParserAST

TranslatorBytecode

InterpreterNative Code

JS Code

JS Code

LexerTokens

ParserAST

TranslatorBytecode

InterpreterNative Code

var x = 10;

var y;

function somar(a, b) {

return a + b;

}

y = 5;

somar(x, y); // 15

JS Code

LexerTokens

ParserAST

TranslatorBytecode

InterpreterMachine Code

var x = 10;

var y;

function somar(a, b) {

return a + b;

}

y = 5;

somar(x, y); // 15

Keyword(var) Identifier(x) Punctuator(=) Numeric(10)

Punctuator(;) Keyword(var) Identifier(y) Punctuator(;)

Keyword(function) Identifier(somar) Punctuator(()

Identifier(a) Punctuator(,) Identifier(b) Punctuator())

Punctuator({) Keyword(return) Identifier(a)

Punctuator(+) Identifier(b) Punctuator(;) Punctuator

(}) Identifier(y) Punctuator(=) Numeric(5) Punctuator

(;) Identifier(somar) Punctuator(() Identifier(x)

Punctuator(,) Identifier(y) Punctuator()) Punctuator(;)

JS Code

LexerTokens

ParserAST

TranslatorBytecode

InterpreterMachine Code

Program

Variable Declarationvar x

Variable Declaratorx = 10

Identifierx

Literal10

Variable Declarationvar y

Variable Declaratory

Identifiery

Function Declarationsomar(a, b) { ... }

Block Statement{ ... }

Return Statementreturn a + b

Binary Expressiona + b

Identifiera

Identifierb

Expression Statementy = 5;

Assigment Statementy = 5

Identifiery

Literal5

Expression Statementsomar(y, x);

Call Expressionsomar(y, x)

Identifiersomar

Argumentsy, x

Identifiery

Identifierx

JS Code

LexerTokens

ParserAST

TranslatorBytecode

InterpreterMachine Code

JITJust In Time

O V8 pula essa parte. Ligeiro né?

AoTAhead of Time

x

JS Code

LexerTokens

ParserAST

TranslatorBytecode

InterpreterMachine Code

JavaScript por design, é interpretado.

Mas na prática é compilado para bytecode ou native code, que será executado pela VM da engine. Deu pra sacar?

Tudo são expressões. Mas como?

O JavaScript executa uma sequencia de expressões:

var x = 10; // 2ª & 4ª expressão

var y; // 3ª expressão

function somar(a, b) { // 1ª expressão

return a + b; // 7ª expressão

}

y = 5; // 5ª expressão

somar(x, y); // 6ª expressão

HOISTING

Na criação do contexto léxico, os compiladores seguem essa ordem:

1. Funções2. Variáveis (somente var, pois let e const não entram na brincadeira)3. Expressões

Agora a ordenação abaixo faz mais sentido né?

var x = 10; // 2ª & 4ª expressão

var y; // 3ª expressão

function somar(a, b) { // 1ª expressão

return a + b; // 7ª expressão

}

y = 5; // 5ª expressão

somar(x, y); // 6ª expressão

function somar(a, b) { // 1ª expressão

return a + b; // 7ª expressão

}

var x; // 2ª expressão

var y; // 3ª expressão

x = 10; // 4ª expressão

y = 5; // 5ª expressão

somar(x, y); // 6ª expressão

Ponto e vírgula: usar ou não usar?

Alto e claro:

Por conveniência podemos omitir o ponto e vírgula ocasionalmente.

AUTOMATIC SEMICOLON INSERTION

1. Declarações de let, const e var2. Declarações de módulos usando import e export3. Declaração de expressões/instruções4. Utilização do debugger, continue, break, return e throw

Sabe o que o Douglas Crockford pensa do seu código sem ponto e vírgula?

É um código extremamente estúpido. Não vou emburrecer o JSMin por conta disso.

Não preciso de ponto e vírgula pois o ASI vai me garantir o rolê né?

Objetos se tornam funções fantasmas

a = b + c

(d + e).print()

//...

a = b + c(d + e).print(); // Ops...

Se quebrar a linha depois do return também dá ruim

function foo () {

return

{

name: "bar"

}

}

foo() // undefined

function foo () {

return; // <<-- tá aqui ó!!!

{

name: "bar"

};

}

foo() // undefined

Nem rola quebrar a linha depois do throw também (e nem é uma boa)

throw

new Error('Shit...')

// Uncaught SyntaxError: Illegal newline after throw

O código que você escreve, pode não ser o mesmo código que será executado.

JavaScript é fracamente tipado. Mas como?

Variáveis no JS não tem valor, mas sim referências para valores.

var amiguinho = 'Dollynho';

Pensa nesse cara como se fosse um ponteiro.

Já o valor podemos considerá-lo tipado.Lembra do JIT?

Vale a pena ver de novo...

JITJust In Time

AoTAhead of Timex

Daí o motivo das constantes “não serem imutáveis”

const a = 10;

a = 20; // Uncaught TypeError: Assignment to constant variable.

const b = {

c: true

};

b = false; // Uncaught TypeError: Assignment to constant variable.

b.c = 'WTF?'; // Ops... ¯\_(ツ)_/¯

Quase tudo é objeto. Mas como?

O que é um objeto?

Um objeto geralmente é um hashmap com pares de chave-valor.

let objetoMaroto = {

chave: "valor"

};

PrimitivosStringNumberBooleanSymbolnullundefined

Antes de entender o bang, vamos lembrar dos tipos

ObjetosObjectFunctionArray

Primitivos● Imutáveis● Comparados por valores

Objetos● Não são imutáveis● Comparados por

instância

Escopo é algo complicado...

Variáveis declaradas na raíz de um arquivo, vazam para o escopo global do browser.

Escopo global no browser

var variavelGLobal = 'To aqui no window';

( () => {

var variavelPrivada = 'O escopo é meu limite. Não o céu.';

window.Deus = 'Filho, estou em todos os lugares';

} )();

Variáveis declaradas na raíz de um arquivo, não vazam para o escopo global como no browser.

Escopo global no Node.js

var variavelPrivada = 'To aqui no módulo, "aka" arquivo';

global.variavelGLobal = 'Sou tipo Deus, saca?';

Escopo em bloco (ES2015)

function escopo() {

{

let a = 'Não vou sair pro escopo externo.';

const b = 'Também estou no escopo do bloco.';

var wesley = '1% blocked, 99% function';

}

console.log( wesley );

console.log( a || b ); // Uncaught ReferenceError: b is not defined

}

E o this?

O this é o contexto de quem chama.

// No escopo global, vai retornar o objeto Window

console.log(this); // window {}

// Se não utilizar o "use strict";, pode vazar para o window o

// escopo das funções globais

function funcaoGlobal() {

console.log(this); // window {}

}

var a = {

b: 10,

c: () => {

console.log(this.b);

}

}

a.c(); // undefined

var a = {

b: 10,

c: function() {

console.log(this.b);

}

}

a.c(); // 10

Também expõe propriedades de um objeto criado com construtor

function Pessoa({ nome, idade, profissao }) {

this.nome = nome;

this.profissao = profissao;

var idade = idade;

this.identidade = () => {

return `${this.nome} tem ${idade} anos e é ${this.profissao}`;

};

}

var frodo = new Pessoa({

nome: 'Frodo',

idade: 24,

profissao: 'Protetor de Anel'

});

frodo.identidade(); // Frodo tem 24 anos e é Protetor de Anel

frodo.idade; // undefined

Transportando escopos

Retorna uma nova função com um escopo definido via parametro

Bind, Call e Apply

var crianca = { idade: 5 };

var adolescente = { idade: 15 };

var adulto = { idade: 30 };

function informarComidaPredileta (pratoPrincipal, acompanhamento) {

return `Tenho ${this.idade} anos e gosto de comer ${pratoPrincipal} com ${acompanhamento}`;

}

informarComidaPredileta.bind(crianca, 'sorvete', 'chocolate' )();

// "Tenho 5 anos e gosto de comer sorvete com chocolate"

informarComidaPredileta. call(adolescente, '1 kilo de comida' , 'qualquer coisa' );

// "Tenho 15 anos e gosto de comer 1 kilo de comida com qualquer coisa"

informarComidaPredileta. apply(adulto, [ 'algo leve' , 'bastante gordura, sal, açucar e coca cola' ]);

// "Tenho 30 anos e gosto de comer algo leve com bastante gordura, sal e coca cola"

Assíncrono não é paralelo

Fila de execução

O velho exemplo do http

http.get('api.concretesolutions.com/users', onSuccessQuePodeRolarQuandoQuiser);

tocarFaroesteCaboclo();

aguardarAtendenteDaTim();

function onSuccessQuePodeRolarQuandoQuiser(response) {

// ...

}

Obrigado!

Twitter @AlanCezarAraujoalan.cezar.silva@gmail.com

www.concretesolutions.com.brblog.concretesolutions.com.br

Rio de Janeiro – Rua São José, 90 – cj. 2121Centro – (21) 2240-2030

São Paulo - Rua Sansão Alves dos Santos, 433 4º andar - Brooklin - (11) 4119-0449

top related