Javascript - 2014

145
#FormaciónEBusiness Mobile Apps Desarrollo en JavaScript Carlos Alonso Pérez

Transcript of Javascript - 2014

Page 1: Javascript - 2014

#FormaciónEBusiness

Mobile Apps Desarrollo en JavaScript Carlos Alonso Pérez

Page 2: Javascript - 2014

#FormaciónEBusiness

COMPARTE Y DEBATE #DIPLOMADOAPPS

Page 3: Javascript - 2014

Antes de empezar... Presentaciones

• Nombre • Edad • Estudios • ¿A qué te dedicas? • ¿Por qué estás aquí? • ¿Qué esperas de este curso? • ¿Qué experiencia tienes con JS, HTML y CSS?

Page 4: Javascript - 2014

Metodología

Page 5: Javascript - 2014

Metodología Práctica

• En la explicación • En labs • En ejercicios

Page 6: Javascript - 2014

Sobre las dudas

Page 7: Javascript - 2014

Índice de contenidos

• Introducción y entorno de desarrollo • Conceptos de programación básicos • Conceptos de programación avanzados

Page 8: Javascript - 2014

Introducción• ¿Qué sabemos de Javascript?

– Historia – ¿Es un lenguaje de programación? ¿de scripting? ¿un subconjunto de Java? – ¿Estructurado u OO? – ¿Compilado o interpretado? – ¿Imperativo, funcional o híbrido? – ¿Fuerte o débilmente tipado? – ¿Dinámico? – ¿Cuáles son sus entornos de ejecución? – ¿Sencillo o difícil? – ¿Potente? – ¿Tiene errores? – ¿Tiene buena o mala reputación?

Page 9: Javascript - 2014

¡¡No conocemos Javascript!!

Page 10: Javascript - 2014

Re-introducción• ¿Quién es Javascript?

– Historia – Lenguaje de scripting más usado del mundo

Page 11: Javascript - 2014

Re-introducción• ¿Quién es Javascript?

– Sintaxis C – Completamente Orientado a Objetos – Interpretado – Funcional Híbrido – Débilmente tipado – Dinámico – Fácil de aprender, difícil de dominar – Muy potente – Sí, tiene errores

Page 12: Javascript - 2014

La reputación de Javascript

Page 13: Javascript - 2014

Entorno de desarrollo• Obligatorio

– Editor de textos – Navegador + debugger – Documentación: https://developer.mozilla.org/en-­‐US

• Opcional – IDE – JSLint: http://www.jslint.com – JSfiddle: http://js:iddle.net

Page 14: Javascript - 2014

Mi elección

++

+ +

Page 15: Javascript - 2014

Programación: Conceptos básicos

• Estructura léxica • Tipos, valores y

variables • Funciones • Clases

Page 16: Javascript - 2014

Pero antes... Debugging

Page 17: Javascript - 2014

Pero antes... Debugging

Lab 1

Page 18: Javascript - 2014

Estructura léxica

• Juego de caracteres: Unicode case sensitive

• Comentarios C • Literales • Sentencias

/* * Literales */121.2“Hello World!”

/* * Sentencias */var a = 1;

Page 19: Javascript - 2014

Estructura léxica

• Identificadores – i, my_variable, _dummy, $str, sí, π

• Palabras reservadas – break delete case do catch else continue false debugger finally default

for function return typeof if switch var in this void instanceof throw while new true with null try

Page 20: Javascript - 2014

Estructura léxica

; es opcional!!

/* * Comportamiento esperado */1 + 2 “hola mundo!”

/* * Comportamiento inesperado! */var f = 21 + f(2 + 3) * 2

Page 21: Javascript - 2014

Tipos primitivos

• Numéricos • Cadenas • undefined • null • Booleanos

Page 22: Javascript - 2014

Number

• Sintaxis: [dígitos][.dígitos][(E|e)(+|-)dígitos] • Enteros:

– 0, 3, 10000000

• Floats: – 3.14, 2345.678, .333333, 6.02e23, 1.45632E-32

Page 23: Javascript - 2014

Number: Valores especiales.

console.log(1E309);console.log(-1E309);console.log(1/0);

Infinityconsole.log(1/-0);console.log(0 == -0);

-0

console.log(1/”hola”);console.log(-1E309);console.log(1/0);

NaN"hola" == NaN;isNaN("hola");(1/-0) == Infinity;isFinite(1/-0);

isFinite() isNaN()

Page 24: Javascript - 2014

String

• Definición => “Hola Mundo!” • Concatenación => “Hola” + “Mundo!” • Longitud => “Hola Mundo!”.length • Array de caracteres => “Hola Mundo!”[0]

Page 25: Javascript - 2014

undefined y null

• undefined => no inicializado

• null => no hay objeto o valor

Page 26: Javascript - 2014

Booleanos

• true y false

• Tabla de verdad: – false => undefined, null, 0, -0, NaN y “” – true => Todo lo demás

Page 27: Javascript - 2014

Detectando tipos

Operador typeof

/* * Detección de tipos */typeof 2typeof 2.33typeof “Hola Mundo!”typeof undefinedtypeof truetypeof null // Es un objeto!!

Page 28: Javascript - 2014

Tipos proporcionados por JS

• Fechas y horas • El objeto global • Wrapper objects • Conversión de tipos (Casting)

Page 29: Javascript - 2014

Fechas y horas

• Clase Date • Documentación:

– https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

/* Ejemplo uso de fechas */var now = new Date();var future = new Date(now.getTime() + 300000);future - now;

Page 30: Javascript - 2014

Fechas y horas: Ejercicio!• Calcular el número de días que han pasado desde

mi nacimiento el 19 - Marzo - 1985. • Documentación:

– https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

Page 31: Javascript - 2014

Fechas y horas: Ejercicio!• Calcular el número de días que han pasado desde

mi nacimiento el 19 - Marzo - 1985. • Documentación:

– https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

/** Solución: 10700.6108…*/

var now = new Date();var carlos = new Date(1985, 2, 19);var millis = now - carlos;millis / 1000 / 60 / 60 / 24;

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

Page 32: Javascript - 2014

El objeto global

• Creado al inicializar el intérprete JS • Es nuestro contexto de ejecución (this) • Proporciona métodos

– isNaN(), isFinite(), ...

/* * El objeto global nos permite usar sus métodos * directamente, sin usar this */isNaN(“hola”);this.isNaN(“hola”);

Page 33: Javascript - 2014

El objeto global

• Proporciona Constructores: – Date, Object, ...

• Almacena nuestras variables globales

/* * Constructores */var now = new this.Date();now;

/* * Almacena variables * globales */var now = new Date();this.now;

Page 34: Javascript - 2014

Wrapper Objects

/* * Ejemplo 1 */var s = “Hola Mundo!”;console.log(typeof s);s.charAt(0);

/* * Ejemplo 2 */var s = “Hola Mundo!”;s.my_dummy_var = 56;s.my_dummy_var;

Conversión automática entre tipos primitivos y su correspondiente ‘wrapper object’

Page 35: Javascript - 2014

Wrapper Objects

/* * Ejemplo 1 */var s = new String(“Hola!”);console.log(typeof s);s.my_dummy_var = 56;s.my_dummy_var;

/* * Ejemplo 2 */var n = new Number(5);console.log(5 == n);5 === n;

Conversión automática entre ‘wrapper objects’ y su tipo primitivo

Page 36: Javascript - 2014

Conversión de tipos (Casting)

/* * Ejemplos */10 + “objects” // “10 objects”“7” * “4” // 28var n = 1 - “x” // NaNn + “objects” // “NaN objects”10 + “” // “10”+”1” // 1“1” - 0 // 1!!”0” //true (doble negación)

Casting implícito

Page 37: Javascript - 2014

Conversión de tipos (Casting)

/* * Ejemplos */Number(“2”) // 2String(false) // “false”Boolean([]) // trueObject(3) // new Number(3)parseInt(“3 min”) // 3parseInt(“0.1”) // 0parseFloat(“0.1”) // 0.1

Casting explícito

Page 38: Javascript - 2014

Variables

• Declaración • Scope

Page 39: Javascript - 2014

Variables: Declaración

/* * Declaración e inicialización */var i; // Declaración simplevar i, j, k; // Declaración múltiplevar i = 0; // Inicialización simplevar i = 0, j = 1, k = 2; // Inicialización múltiplevar a, b = “hola”; // Declaración + inicialización

Page 40: Javascript - 2014

Variables: Redeclaración y omisión

/* * Redeclaración */var a = 1;var a = 2;a; // 2

/* * Redeclaración */var a = 1;var a;a; // 1

/* * Omisión */a = 1;a // 1

Page 41: Javascript - 2014

Variables: Scope

var scope = “global”;function checkscope() {

scope = “local”;}checkscope();scope; // local

• Global: Variables disponibles en cualquier sección del código.

var scope = “global”;function checkscope() {

var scope = “local”;}checkscope();scope; // global

• Local: Variables definidas dentro de una función.

• Eclipsan variables globales con el mismo nombre.

Page 42: Javascript - 2014

Variables: Scope

El problema de definir variables omitiendo ‘var’.

scope = “global”;function checkscope() {

scope = “local”;localvar = “local”;

}checkscope();scope; // local => ¡¡Ha sido modificada!!localvar; // local => ¡¡Está definida!!

Page 43: Javascript - 2014

Variables: Scope

Función: Característica de JS. La variable está disponible en todo el cuerpo de la función. No sólo en el bloque donde se define.

function checkscope() {if (true) {

var j = 1;if (true) {

var k = 2;}

}console.log(j); // 1console.log(k); // 2

}checkscope();

Page 44: Javascript - 2014

Variables: Scope

Variable hoisting: Otra característica de JS. ¡¡Las variables definidas en una función están disponibles antes incluso de ser definidas!!

function checkscope() {console.log(scope); // undefinedvar scope = “local”;console.log(scope); // local

}checkscope();

Page 45: Javascript - 2014

Objetos

• Tipo de dato fundamental de JS • Colección no ordenada de propiedades

con nombre y valor • Dinámicos

Page 46: Javascript - 2014

Objetos: El ‘prototype’

• Todas las clases JS tienen un prototype asociado que define sus atributos y métodos.

• Todos los objetos de una clase tendrán todos los atributos y métodos de su prototype y pueden, además, tener otros atributos y métodos propios.

Page 47: Javascript - 2014

Objetos: Creación

• Literal

var empty = {}; var point = {x:1, y:3}; var book = { title: "The title", author: { name: "author name", surname: "author surname" }};

• Operador ‘new’

var o = new Object();var d = new Date();

Page 48: Javascript - 2014

Objetos: Propiedades

• Tienen un nombre, un valor y atributos. • Son accesibles con notación de punto (.) o

corchetes ([]) • Se pueden añadir o eliminar en tiempo de

ejecución. • Pueden ser propias o heredadas.

Page 49: Javascript - 2014

Objetos: Propiedades

• Añadiendo propiedades

var o = {};o.first_prop = “first”;o[“second_prop”] = “second”;

• Accediendo a propiedades

o[“first_prop”]; // firsto.second_prop; // second

Page 50: Javascript - 2014

Objetos: Propiedades

Borrando propiedades

delete o.first_prop;

¡JS es dinámico!

Page 51: Javascript - 2014

Propiedades: Ejercicio!• Crear una función que reciba tres parámetros, un objeto, el nombre

de una propiedad y un valor. • La función debe comprobar si el objeto tiene una propiedad con ese

nombre y si la tiene retornar el valor y sino definirla, asignar el valor recibido en el tercer parámetro y retornarlo.

Page 52: Javascript - 2014

Propiedades: Ejercicio!• Crear una función que reciba tres parámetros, un objeto, el nombre

de una propiedad y un valor. • La función debe comprobar si el objeto tiene una propiedad con ese

nombre y si la tiene retornar el valor y sino definirla, asignar el valor recibido en el tercer parámetro y retornarlo.

function f(obj, property, value){

if (!obj[property]) {obj[property] = value;

}return obj[property];

}

Page 53: Javascript - 2014

Propiedades: Detección y enumeración

• Operador ‘in’:

var o = { x: 1 };“x” in o; // true“y” in o; // false“toString” in o; // true

• Bucle for/in:

var o = { x: 1, y: 2, z: 3 };for(p in o) {

console.log(p);console.log(o[p]);

}

Page 54: Javascript - 2014

Propiedades: Ejercicio!Reescribir la función del ejercicio anterior utilizando alguno de los enumeradores vistos.

Page 55: Javascript - 2014

Propiedades: Ejercicio!Reescribir la función del ejercicio anterior utilizando alguno de los enumeradores vistos.

function f(obj, property, value){

if (!(property in obj)) {obj[property] = value;

}return obj[property];

}

Page 56: Javascript - 2014

Arrays

• Creación

var empty = [];var fill = [1, 2, 3, 4];var empty2 = new Array();var withSize = new Array(10);var fill2 = new Array(1, 2, 3, 4);

• Pueden contener cualquier tipo de objeto

var misc = [1, “hola”, true, , {}, []];var misc2 = new Array(1, “hola”, true, {}, []);

Page 57: Javascript - 2014

Arrays

• Crecen dinámicamente

var a = [];a[3] = “hola”;a;

• Son objetos, por tanto admiten propiedades!!

var a = [];a.hola = “hola”;a.hola;

Page 58: Javascript - 2014

Funciones

• Son tipos primitivos: • Se pueden usar como variables • Se pueden pasar como argumentos a otras funciones • Pueden ser el retorno de otra función • Se les pueden asignar propiedades e incluso invocar

métodos en ellas.

Page 59: Javascript - 2014

Funciones

Definición // Como expresiónfunction f(x) {

return x + 1;}

// Como sentenciavar f = function(x) {

return x + 1;}

// Anidadafunction hypotenuse(a, b) {

function square(x) { return x * x; };return Math.sqrt(square(a) + square(b));

}

Page 60: Javascript - 2014

Funciones: Scope léxico

Tienen acceso a todas las variables definidas en el bloque donde son definidas.

function a(x) {var y = “y”;function b() { console.log(x + “ “ + y + “ “ + z); // x y z}var z = “z”;b();

}a(“x”);

Page 61: Javascript - 2014

Métodos

• Son funciones que son propiedades de algún objeto.

• Se ejecutan en el contexto del objeto.

var o = {m: function() {

console.log(this === o);}

}

Page 62: Javascript - 2014

Métodos con funciones anidadas

Fuente común de errores debido al contexto (this).

var o = {m: function() {

console.log(this === o); // truefunction f() { console.log(this === o); // false console.log(this); // Es el objeto global!!}f();

}}o.m();

Page 63: Javascript - 2014

Métodos con funciones anidadas

La solución es el uso del scope léxico

var o = {m: function() {

var self = this;function f() { console.log(self === o); // true}f();

}}o.m();

Page 64: Javascript - 2014

Funciones: Ejercicio!¿Los argumentos en JS se pasan por valor o por referencia? ¿Y sin son objetos?

Page 65: Javascript - 2014

Funciones: Ejercicio!¿Los argumentos en JS se pasan por valor o por referencia? ¿Y sin son objetos?

/** Solución*/

function f (value, object) {value ++;object.x ++;

}

var o = { x: 1 };var v = 1;f(v, o);console.log(o);console.log(v);

Page 66: Javascript - 2014

Funciones: Argumentos

No se comprueba ni el tipo ni el número

function a(x, y) {console.log(“Función ejecutada correctamente”);

}a(1); // Con un argumento menosa(1, 2, 3); // Con un argumento mas

Page 67: Javascript - 2014

Funciones: Argumentos

Argumentos opcionales = undefined

function saySomething(/*optional*/something) {

something = something || “hello”;console.log(something);

}

saySomething();saySomething(“goodbye”);

Page 68: Javascript - 2014

Funciones: Argumentos• Argumentos extra: ‘varargs functions’. • JS proporciona a todas las funciones un array ‘arguments’

• Nos permite comprobar si una función se ha invocado con el número correcto de argumentos.

• Nos permite definir funciones que trabajen sobre un número variable de argumentos.

function f(x, y, z) {if (arguments.length != 3) {

throw new Error(“Wrong arguments number”);}// ...

}

Page 69: Javascript - 2014

Funciones: Ejercicio!• Definir una función que retorne el número máximo de todos los que recibe

como argumentos. • La función no debe definir ningún argumento:

• function max() { ... } • Pista: Podéis usar Number.INFINITY y Number.NEGATIVE_INFINITY

Page 70: Javascript - 2014

Funciones: Ejercicio!• Definir una función que retorne el número máximo de todos los que recibe

como argumentos. • La función no debe definir ningún argumento:

• function max() { ... } • Pista: Podéis usar Number.INFINITY y Number.NEGATIVE_INFINITY

function max(/* ... */) { var max = Number.NEGATIVE_INFINITY; for (var i = 0 ; i < arguments.length ; ++i) { if (arguments[i] > max) { max = arguments[i] } } return max; } console.log(max()); console.log(max(1, 2, 1000, 3));

Page 71: Javascript - 2014

Funciones: Propiedades

Las funciones son objetos, por tanto pueden tener propiedades.

function uniqueValue() {return uniqueValue.c ++;

}uniqueValue.c = 1;

console.log(uniqueValue());console.log(uniqueValue());console.log(uniqueValue());

Page 72: Javascript - 2014

Clases

Conjunto de objetos que heredan propiedades del mismo prototipo.

function range(from, to) {var r = Object.create(range.prototype);r.from = from;r.to = to;return r;

}

range.prototype = {includes: function(x) {

return this.from <= x && x <= this.to;},toString: function() {

return “(“ + this.from + “..” + this.to + “)”;}

};

var r = range(1, 3);console.log(r.includes(2));r.toString();

Page 73: Javascript - 2014

Clases: Constructores

En JS se define una clase mediante una función constructor y su prototype.

function Range(from, to) {this.from = from;this.to = to;

}

Range.prototype = {includes: function(x) {

return this.from <= x && x <= this.to;},toString: function() {

return “(“ + this.from + “..” + this.to + “)”;}

};

var r = new Range(1, 3);console.log(r.includes(2));r.toString();

Page 74: Javascript - 2014

Clases: operador ‘new’

• Convierte una función simple en un constructor: • El intérprete creará un nuevo objeto. • Lo convertirá en el contexto actual (this). • Le asignará la propiedad prototype al prototype de la

función • Lo usará como retorno de la función (constructor).

Page 75: Javascript - 2014

Operador ‘new’: Ejercicio!• ¿Qué ocurriría si, por error, invocamos un constructor sin el

operador new? • ¿Qué objeto se creará? • ¿Qué efecto tendrá el código del constructor? • ¿Cuál será el valor retornado?

Page 76: Javascript - 2014

Operador ‘new’: Ejercicio!• ¿Qué ocurriría si, por error, invocamos un constructor sin el

operador new? • ¿Qué objeto se creará? • ¿Qué efecto tendrá el código del constructor? • ¿Cuál será el valor retornado?

• No se creará ningún objeto nuevo. • El contexto desde el que se invoque la función sufrirá las

modificaciones resultantes del código del constructor. • El valor de retorno será undefined.

Page 77: Javascript - 2014

Clases: Herencia

• Heredar en JS significa que el prototipo de la función constructor de la clase hija es un objeto de la clase padre.

• La función constructor de la clase padre tiene como prototype un objeto de su clase padre.

• La función constructor de Object es la única del lenguaje cuyo prototype es null.

• Así se constituye la cadena de prototipos (prototype chain)

Object()

proto = null

Parent()

proto = Object

Child()

proto = Parent

Page 78: Javascript - 2014

Clases: Herenciafunction Parent() {}

Parent.prototype = { sayHello: function() { console.log("Hello"); }};

function Child() {}

Child.prototype = new Parent(); Child.prototype.sayGoodbye = function() { console.log("Goodbye");};

var child = new Child();child.sayHello();child.sayGoodbye();child.toString();

Object()

proto = null

Parent()

proto = Object

Child()

proto = Parent

Page 79: Javascript - 2014

Detectando clases• Mediante el prototype: Un objeto es de una clase si su prototype y el de

su constructor son el mismo.

• Los objetos de una clase no tienen propiedad prototype definida. La propiedad prototype es de la función constructora.

// En el ejemplo anterior...var child = new Child();child.prototype; // undefined!!

var child = new Child();Object.getPrototypeOf(child); // Retorna el objeto Parent que asignamos como// prototype a la función Child y extendimos

Page 80: Javascript - 2014

Detectando clases: Ejercicio!Escribir una función que reciba dos argumentos, un objeto y un constructor e indique si el objeto es de ese tipo o de algún ancestro de ese tipo.

Page 81: Javascript - 2014

Detectando clases: Ejercicio!Escribir una función que reciba dos argumentos, un objeto y un constructor e indique si el objeto es de ese tipo o de algún ancestro de ese tipo.

function isKindOfClass(object, klazz) { var ret = false; while (!ret && object) { ret = Object.getPrototypeOf(object) === klazz.prototype; object = Object.getPrototypeOf(object); } return ret; }function Test() {}

var t = new Test(); isKindOfClass(t, Test); // true isKindOfClass(t, Object); // true isKindOfClass(t, String); // false

Page 82: Javascript - 2014

Detectando clases

Operador instanceof: Detecta si un objeto es instancia de una clase o ancestro.

// En el ejemplo anterior...var child = new Child();child instanceOf Parent; // truechild instanceOf Object; // truechild instanceOf String; // false

Page 83: Javascript - 2014

Detectando clases

Propiedad constructor: Propiedad que tienen todos los prototipos, aunque JS no siempre puede asignarla.

Parent()prototype

Constructor Prototype

constructor

sayHello:  ...

Instancias

new  Parent()hereda

hereda new  Parent()

Page 84: Javascript - 2014

Detectando clases

JS no puede asignarla automáticamente.

function Parent() {}Parent.prototype = { constructor: Parent, sayHello: function() { console.log("Hello"); }};

JS sí puede asignarla automáticamente.

function Parent() {}Parent.prototype.sayHello = function() { console.log("Hello");};(new Parent()).constructor;

Page 85: Javascript - 2014

Modificación dinámica de clasesJS permite modificar los objetos prototype de cualquier constructor en tiempo de ejecución y la modificación afectará incluso a los objetos ya existentes.

function Parent() {}

Parent.prototype = {sayHello: function() {

console.log("Hello");}

};

var p = new Parent();

Parent.prototype.sayHi = function() {console.log(“Hi”);

};p.sayHi();

Page 86: Javascript - 2014

Modificación dinámica de clases: Ejercicio!

• Modificar la clase Number y añadirle un método que nos indique si su valor es par o no.

• Mirad la documentación de Number y su prototype

Page 87: Javascript - 2014

Modificación dinámica de clases: Ejercicio!

• Modificar la clase Number y añadirle un método que nos indique si su valor es par o no.

• Mirad la documentación de Number y su prototype

/** Solución*/

Number.prototype.even = function() {return this.valueOf() % 2 == 0;

}

var n = 4;n.even();

Page 88: Javascript - 2014

Métodos estáticos

No existen en JS, pero es tan flexible que podemos simularlos como métodos de la función constructora.

Parent.buildNew = function() {return new Parent();

}

var p = Parent.buildNew();

Page 89: Javascript - 2014

Programación: Conceptos avanzados

• Scope Chain • Closures • Subclases • Clases Abstractas • Comparación de objetos • Módulos • Strict Mode

Page 90: Javascript - 2014

Scope Chain: Conceptos

• Scope: Conjunto de líneas de código en las que una variable está definida. Puede ser: – Global: Variables globales, que están definidas en

todo el programa. – Local: Variables definidas en la función que son

declaradas y en las funciones anidadas dentro de esa función.

Page 91: Javascript - 2014

Scope Chain• JS almacena las variables con scope local para cada fragmento

de código como propiedades de un objeto interno. • El scope chain es una cadena (lista) de objetos que definen las

variables que están en scope. • Cada fragmento de código tiene un scope chain asociado. • Cuando JS necesita buscar una variable recorre el scope chain

de forma ordenada hasta que encuentra algún objeto de la cadena que define la variable o la cadena termina y lanzaría un ReferenceError.

• Cuando una función es invocada, un nuevo objeto se añade al scope chain con las variables locales de la función.

Page 92: Javascript - 2014

Scope Chain

var a = 1;function f(c) {

var b = 2;// Scope chain 2

}// Scope chain 1f(3);

Ejemplo:

{ a: 1,f: function() }

Scope Chain 1{ a: 1,f: function() }

{ c: 3, b: 2 }

Scope Chain 2

El proceso de resolución de variables sigue la cadena en el sentido de las flechas.

Page 93: Javascript - 2014

Scope Chain

var a = 1;function f(c) {

var b = 2;function s(d) {

// Scope chain(i)return b + c;

}return s(4);

}for (var i = 0 ; i < 3 ; ++i) {

f(i);}

Ejemplo con funciones anidadas:{ a: 1,f: function(),i: i }

{ c: i,b: 2,s: func }

Scope Chain(i)

{ d: 4 }

Page 94: Javascript - 2014

Scope chain: Ejercicio!

var a = 1;function f(c) {

var b = 2;function s(d) {

// Scope chain(i, j)return b + c + d;

}return s(j);

}for (var i = 0 ; i < 3 ; ++i) {

for (var j = 0 ; j < 3 ; ++j) {f(i);

}}

• Dibujar el Scope Chain que existirá en el punto del comentario.

• Recordad:

• Que ese Scope Chain dependerá de las variables i y j.

• Que cada vez que una función es invocada, sus funciones anidadas son definidas nuevamente

• Que solo se añade un nuevo objeto al Scope Chain cuando ocurre una invocación de una función, pero el estado del resto de objetos del Scope Chain puede variar en cualquier momento (nuevas variables o cambio de valor de variables ya existentes.)

Page 95: Javascript - 2014

Scope chain: Solución!

{ a: 1,f: function(),i: i,j: j }

{ c: i,b: 2,s: func }

Scope Chain(i, j)

{ d: j }

var a = 1;function f(c) {

var b = 2;function s(d) {

// Scope chain(i, j)return b + c + d;

}return s(j);

}for (var i = 0 ; i < 3 ; ++i) {

for (var j = 0 ; j < 3 ; ++j) {f(i);

}}

¿Dudas? ¿Preguntas? ¿Repetimos?

Page 96: Javascript - 2014

Closures

• JS usa Scope Léxico, es decir, las funciones son ejecutadas usando el scope existente cuando fueron definidas, no cuando son invocadas.

• Para implementar Scope Léxico, cada función guarda internamente el código a ejecutar y una copia del scope chain existente cuando se define.

• Objeto función + Scope Chain = Closure

Page 97: Javascript - 2014

Closures• Mismo Scope Chain

var scope = “global scope”;function checkscope() {

var scope = “local scope”;function f() {

return scope;}return f();

}checkscope(); // “local scope”

• Diferente Scope Chain

var scope = “global scope”;function checkscope() {

var scope = “local scope”;function f() {

return scope;}return f;

}a = checkscope();a(); // “local scope”

Sorprendidos, ¿verdad?

Page 98: Javascript - 2014

Closures

Mismo Scope Chain

var scope = “global scope”;function checkscope() {

var scope = “local scope”;function f() {

// Scope chainreturn scope;

}return f();

}checkscope(); // “local scope”

{ scope: “global”,checkscope: func}

{ scope: “local”,f: func }

{}

Scope chain

{ scope: “global”,checkscope: func}

{ scope: “local”,f: func }

{}

Scope chain f

Scope chain f()

Page 99: Javascript - 2014

Closures

Distinto Scope Chain

var scope = “global scope”;function checkscope() {

var scope = “local scope”;function f() {

// Scope chainreturn scope;

}return f;

}var fn = checkscope();fn(); // “local scope”

{ scope: “global”,checkscope: funcfn: func}

{}

Scope chain { scope: “global”,checkscope: func}

{ scope: “local”,f: func }

{}

Scope chain f

Scope chain f()

Page 100: Javascript - 2014

Closures: Private properties

Un posible uso de las closures es definir propiedades privadas en objetos.

function Test() {var my_private = “private”;this.read_private_var = function() {

return my_private;}

}var t = new Test();t.my_private; // undefinedt.read_private_var(); // “private”

Page 101: Javascript - 2014

Closures: Ejercicio!

• Definir una clase Counter que tenga únicamente dos métodos públicos y ninguna propiedad: • count(): Devuelve el número de llamadas recibidas a esta

función. • reset(): Pone a 0 el contador

Page 102: Javascript - 2014

Closures: Ejercicio!

• Definir una clase Counter que tenga únicamente dos métodos públicos y ninguna propiedad: • count(): Devuelve el número de llamadas recibidas a esta

función. • reset(): Pone a 0 el contador function Counter() {

var counter = 0;this.count = function() {

counter ++;return counter;

};this.reset = function() {

counter = 0;};

}

Page 103: Javascript - 2014

Subclases

• Hasta ahora, cuando necesitamos extender una clase, simplemente encadenamos sus prototipos.

• ¿Qué ocurre cuando necesitamos inicializar el padre?

function Parent() {this.initialized = true;

}

Parent.prototype = {initialized: false,

sayHello: function() {if (this.initialized) {

console.log("Hello");}

}};

function Child() {}

Child.prototype = new Parent(); Child.prototype.sayGoodbye = function() { console.log("Goodbye");};

var c = new Child();child.sayHello();

Page 104: Javascript - 2014

Subclases: funciones call y apply• call y apply son métodos de las funciones que nos

permiten invocarlas indirectamente, ¡como si fueran métodos de otros objetos!.

• Se diferencian en la forma de recibir los argumentos.

var num = { value: 1 };

function sum(value) {return this.value + value;

}

console.log(sum.apply(num, [1]));console.log(sum.call(num, 2));

Page 105: Javascript - 2014

Subclases

La solución es ‘aplicar’ el constructor del padre a nuestro contexto.

function Child() {Parent.apply(this, arguments);

}

Page 106: Javascript - 2014

Subclases: Ejercicio!

En el código de ejemplo, ¿cómo haríais para que la llamada a sayHello en el hijo ejecute también sayHello en el padre?

function Parent() {}

Parent.prototype = { sayHello: function() {

console.log("Hello"); }};

function Child() {}

Child.prototype = new Parent(); Child.prototype.sayHello = function() { console.log(" from child");};

var c = new Child();child.sayHello();

Page 107: Javascript - 2014

Subclases: Solución!

Igual que invocamos al constructor de la función padre con apply, hacemos lo mismo con la función sayHello, referenciándola a través de su prototype.

Child.prototype.sayHello = function() {Parent.prototype.sayHello.apply(this, arguments);

console.log(" from child");};

Page 108: Javascript - 2014

Clases Abstractas function Parent() {}

Parent.prototype = { sayHello: function() {

throw new Error(“Abstract method!”); }};

function Child() {}

Child.prototype = new Parent(); Child.prototype.sayHello = function() { console.log("Hello");};

var c = new Child();child.sayHello();

Page 109: Javascript - 2014

Comparación de objetos• Igualdad (==). True si son…

• …cadenas idénticas • …equivalentes numéricamente • …el mismo objeto • …valores booleanos idénticos • …expresiones de distintos

tipos, pero pueden reducirse a alguno de estos casos anteriores

“abc” == “abc”;

2 + 3 == 5;

var a = {};a == a;

true == !false

new Number(3) == 3

Page 110: Javascript - 2014

Comparación de objetos• Identidad (===). True si son…

• …cadenas idénticas • …equivalentes numéricamente • …el mismo objeto • …valores booleanos idénticos

“abc” === “abc”;

2 + 3 === 5;

var a = {};a === a;

true === !false

Mismas reglas que en el caso de la igualdad, excepto que no se hace conversión de tipos

Page 111: Javascript - 2014

Comparación de objetos: Ejercicio!• new Number(3) == new Number(3) // False!• ¿Cómo podemos entonces comparar el valor de dos objetos

Number? Implementar una solución • Pista: En otros lenguajes como Java, todas las clases definen un

método equals() para comparar, en vez de ==.

Page 112: Javascript - 2014

Comparación de objetos: Ejercicio!• new Number(3) == new Number(3) // False!• ¿Cómo podemos entonces comparar el valor de dos objetos

Number? Implementar una solución • Pista: En otros lenguajes como Java, todas las clases definen un

método equals() para comparar, en vez de ==.

Number.prototype.equals = function(obj) {if (!obj instanceof Number) {

return false;}return this.valueOf() == obj.valueOf();

};(new Number(3)).equals(new Number(3));

Page 113: Javascript - 2014

Módulos• Necesitamos definir módulos si queremos:

• Mantener el código organizado. • Poder mantenerlo. • Reutilizarlo • ...

• Pero JS no proporciona una forma estándar, por tanto tenemos que diseñar nuestra propia manera de hacerlo.

• Objetivo: Definir un módulo que se incluya en otros programas JS y no altere el entorno. • Minimizar el número de variables globales definidas.

Page 114: Javascript - 2014

MódulosPaso 1: Utilizar un solo objeto como namespace

/* * Definición */

var collections = {};collections.Set = function() {

//Constructor};collections.Set.prototype ...collections.OrderedMap = function() {

//Constructor}collections.OrderedMap.prototype ...

/* * Uso */

var s = new collections.Set(...);

// pseudo-importvar Set = collections.Set;var s2 = new Set(...);

Page 115: Javascript - 2014

Módulos

Paso 2: Utilizar funciones como namespace privado

/* * Definición */

var collections = {};(function(){

function Set() {//Constructor

};Set.prototype ...function OrderedMap() {

//Constructor}OrderedMap.prototype ...

var api_private_var;function api_private_func(){};

collections.Set = Set;collections.OrderedMap = OrderedMap;

})();

Page 116: Javascript - 2014

MódulosPaso 3: Separar cada clase en un archivo

/* * collections/set.js */

if (!collections) {collections = {};

}(function() {

function Set() {//Constructor

};Set.prototype ...var set_private_var;

collections.Set = Set;})();

/* * collections/ordered_map.js */

var collections = collections || {};(function() {

function OrderedMap() {//Constructor

}OrderedMap.prototype ...var orderedMap_private_var;

collections.OrderedMap = OrderedMap;})();

Page 117: Javascript - 2014

Módulos: Ejercicio!

• Escribir el contador con count() y reset() como componente de un módulo llamado utils. • Nota: El constructor no

debe contener código.

Page 118: Javascript - 2014

Módulos: Ejercicio!

• Escribir el contador con count() y reset() como componente de un módulo llamado utils. • Nota: El constructor no

debe contener código.

/* * utils/counter.js */var utils;if (!utils) {

utils = {};}(function() {

function Counter() {//Constructor

}var value = 0;Counter.prototype.count = function() {

value ++;return value;

};Counter.prototype.reset = function() {

value = 0;};utils.Counter = Counter;

})();

Page 119: Javascript - 2014

Modo Strict

• Modo de operación de JS que restringe algunas acciones y lanza más errores • Detecta errores de código comunes y lanza errores. • Prohibe o lanza errores cuando se realizan acciones

potencialmente peligrosas • Deshabilita características no recomendadas.

Page 120: Javascript - 2014

Modo Strict: Activación

<script type=“text/javascript”>“use strict”;

</script>

function strict_func(){ "use strict"; // ...}

• Para todo el script

• Sólo una función

// Código no strict (function(){ "use strict"; // Código strict...})(); // Código no strict

• Módulo

Page 121: Javascript - 2014

Modo Strict: Variables y propiedades

var myvar = 1;…myvr = 2; // ReferenceError!

• Prohibe declarar variables sin la palabra reservada var.

var o = { a: 1, a: 2 }; // SyntaxError

• Prohibe declarar dos propiedades con el mismo nombre.

Page 122: Javascript - 2014

Modo Strict: Funciones

function f() { arguments = ‘abc’; // SyntaxError}

• Prohibe sobreescribir el array arguments

function f(arg, arg) { // SyntaxError}

• Prohibe nombrar dos argumentos de una función iguales

Page 123: Javascript - 2014

Modo Strict: Más información

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode

Page 124: Javascript - 2014

Preguntas de entrevistas

• ¿Cuál es el motivo de rodear todo el código de un archivo JS en una función?

Page 125: Javascript - 2014

Preguntas de entrevistas

• ¿Cuál es el motivo de rodear todo el código de un archivo JS en una función?

Mediante esta técnica creamos una closure alrededor del contenido del archivo y un namespace privado controlando así

qué variables/métodos serán visibles desde el exterior y evitando posibles conflictos de nombres.

Page 126: Javascript - 2014

Preguntas de entrevistas

• ¿Qué es NaN? ¿Cómo podemos saber si un valor es NaN?

Page 127: Javascript - 2014

Preguntas de entrevistas

• ¿Qué es NaN? ¿Cómo podemos saber si un valor es NaN?

El valor NaN representa un valor no numérico. Éste valor resulta de operaciones que no pueden ser completadas,

normalmente, porque alguno de sus operandos no es numérico (‘abc’ / 2).

Debido a que NaN == NaN es falso, la única forma de comprobar si un valor es NaN es mediante la función isNaN()

Page 128: Javascript - 2014

Preguntas de entrevistas

• ¿Cuál es el significado de incluir “use strict” en un script? ¿Cuáles son los beneficios de hacerlo?

Page 129: Javascript - 2014

Preguntas de entrevistas

• ¿Cuál es el significado de incluir “use strict” en un script? ¿Cuáles son los beneficios de hacerlo?

“use strict” es una forma de habilitar modo estricto JS durante un script o una función. Éste modo nos ayuda a evitar errores comunes.

Las ventajas de hacerlo son:• Evitar definir variables globales por error.• Evitar definir dos propiedades con mismo nombre en un objeto.• Evitar nombrar dos argumentos de una función iguales.• Evitar sobreescribir el array arguments de una función.• …

Page 130: Javascript - 2014

Preguntas de entrevistas

• Escribir una función que retorne un booleano que indique si una cadena es un palíndromo o no.

• Puntos extra por hacerlo en una sola línea (< 80 caracteres)

Page 131: Javascript - 2014

Preguntas de entrevistas

• Escribir una función que retorne un booleano que indique si una cadena es un palíndromo o no.

• Puntos extra por hacerlo en una sola línea (< 80 caracteres)

function isPalindrome(str) { return str.split('').reverse().join('') === str; }

Page 132: Javascript - 2014

Preguntas de entrevistas

http://www.toptal.com/javascript/interview-questions#.

Page 133: Javascript - 2014

Programación: Extensión de contenido

• Detección avanzada de propiedades • Accessor properties • Atributos de las propiedades

Page 134: Javascript - 2014

Propiedades: Detección• Operador ‘in’: Detecta propiedades propias o heredadas.

var o = { x: 1 };“x” in o; // true“y” in o; // false“toString” in o; // true

• Método hasOwnProperty(): Detecta propiedades propias, no heredadas, sean enumerables o no.

var o = { x: 1 };o.hasOwnProperty(“x”); // trueo.hasOwnProperty(“y”); // falseo.hasOwnProperty(“toString”); // false

Page 135: Javascript - 2014

Propiedades: Detección

• Método propertyIsEnumerable(): Detecta propiedades propias y enumerables

var o = { x: 1 };o.propertyIsEnumerable(“x”); // trueo.propertyIsEnumerable(“y”); // falseo.propertyIsEnumerable(“toString”); // false

Page 136: Javascript - 2014

Propiedades: Enumeración• Bucle for/in: Propiedades propias o heredadas enumerables

var o = { x: 1, y: 2, z: 3 };for(p in o) {

console.log(p);console.log(o[p]);

}

• Método Object.keys(objeto): Retorna un Array con las propiedades propias y enumerables

• Método Object.getOwnPropertyNames(objeto): Retorna un Array con las propiedades propias, sean enumerables o no

Page 137: Javascript - 2014

Propiedades: ComparativaMétodo  de  Acceso Propias Heredadas Enumerables No  enumerables

Acceso  simple  (.  ó  []) Sí Sí Sí Sí

Operador  in Sí Sí Sí Sí

Método  hasOwnProperty()

Sí No Sí Sí

Método  propertyIsEnumerable() Sí No Sí No

Bucle  for/in Sí Sí Sí No

Object.keys() Sí No Sí No

Object.getOwnPropertyNames()

Sí No Sí Sí

Page 138: Javascript - 2014

Accessor properties

Consultar o asignar una ‘accessor property’ significa la ejecución del método get/set correspondiente

var o = {_a: 3,get a() {

return this._a;},set a(value) {

this._a = value;}

};o.a = 4;o.a;

Page 139: Javascript - 2014

Propiedades: Atributos

• Value: El propio valor de la propiedad. • Writable: Determina si es modificable o no. • Get: Función getter • Set: Función setter. • Enumerable: Determina si la propiedad es enumerable o

no. • Configurable: Determina si los estos atributos pueden ser

modificados o no.

Page 140: Javascript - 2014

Atributos: AplicabilidadAtributo Data  Property Accessor  property

Value Sí No

Writable Sí No

Get No Sí

Set No Sí

Enumerable Sí Sí

Configurable Sí Sí

Page 141: Javascript - 2014

Propiedades: Manejando atributos

Método Object.getOwnPropertyDescriptor(): Retorna un objeto que describe los atributos de la propiedad.

/* * Obtener Property Descriptor * para una propiedad */var o = { x: 1, y: 2 };Object.getOwnPropertyDescriptor(o, “x”);

Page 142: Javascript - 2014

Propiedades: Manejando atributos

Método Object.defineProperty(): Crea o modifica los atributos de una propiedad si ésta es propia y configurable.

var descriptor = { value: 1, writable: true, enumerable: false, configurable: true};var o = {};Object.defineProperty(0, “x”, descriptor);o.x; // 1Object.keys(o); // []

Page 143: Javascript - 2014

Manejando atributos: Ejercicio!

• Dada esta inicialización, ¿se podría cambiar el valor de o.x? ¿Y el de o1.x? ¿Cómo?

• Pista: ¿Cuál es el valor por defecto del atributo configurable?

var o = {};Object.defineProperty(o, “x”, { value: 1, writable: false });

var o1 = { x: 1 };Object.defineProperty(o1, “x”, { writable: false });

Page 144: Javascript - 2014

Manejando atributos: Solución• La solución está en el atributo configurable de la propiedad y los valores

por defecto, que dependen del método que usemos para definir la propiedad. • Definición literal: Todos los atributos = true. • Definición usando Object.defineProperty: Todos los atributos no

especificados = false.

Object.defineProperty(o, “x”, { value: 2 }); // Error!! x no es configurable

Object.defineProperty(o1, “x”, { value: 2 }); // OK

Page 145: Javascript - 2014

#FormaciónEBusiness

GRACIAS. Carlos Alonso Pérez @calonso