JavaScript – o k ase?



JavaScript – o k ase?

0 2


presentacion-javascript


On Github otorras / presentacion-javascript

JavaScript

o k ase?

Creado por Oriol Torras / @uriusfurius

Constructores

Funciones diseñadas para ser usadas con el operador new. Inicializan un objeto recién creado, añadiendo propiedades a this.

function Rectangle(w, h) {
  this.width = w;
  this.height = h;
}

var rect1 = new Rectangle(2, 4); // rect1 = { width: 2, height: 4 };
var rect2 = new Rectangle(8.5, 11); // rect2 = { width: 8.5, height: 11 };

Prototipos y herencia

function Rectangle(w, h) {
  this.width = w;
  this.height = h;
  this.area = function() { return this.width * this.height; };
}

Prototipos y herencia

  • El prototipo de un objeto es el valor de la propiedad prototype de su constructor
  • Todas las funciones tienen una propiedad prototype
  • El objeto prototype se inicializa con la propiedad constructor

Prototipos y herencia

function Rectangle(w, h) {
  this.width = w;
  this.height = h;
}

Rectangle.prototype.area = function() {
  return this.width * this.height;
};

Prototipos y herencia

Puede ser util usar herencia basada en prototipos sin constructores

function extend(proto) {
  function F() {}
  F.prototype = proto;
  return new F();
}

Evita tener que crear una función constructora con nombre. Funcionalidad añadida en ES5 Object.create()

Prototipos y herencia

Para distinguir las propiedades propias del objeto de las de su prototipo usaremos el método Object.hasOwnProperty()

var r = new Rectangle(2, 3);
r.hasOwnProperty('width'); // true
r.hasOwnProperty('area'); // false
'area' in r; // true

Lectura y escritura de propiedades heredadas

En caso de no existir la propiedad directamente en el objeto se lee del prototipo

La escritura siempre se hace sobre el objeto nunca en el prototipo

Extendiendo tipos

  • Añadiendo métodos
  • Bad practice
  • Técnicas defensivas
  • Algunos métodos ahora forman parte del lenguaje

Extendiendo tipos (i)

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

Extendiendo tipos (ii)

if (!Function.prototype.bind) {
  Function.prototype.bind = function(scope) {
    var self = this, args = [].slice.call(arguments, 1);

    return function() {
      return self.apply(scope, args.concat(arguments));
    };
  };
}

Extendiendo tipos (iii)

if (!Number.prototype.add) {
  Number.prototype.add = function(num) {
    return this + num;
  };
}

(2).add(3) // 5

2..add(3) // 5

Extendiendo tipos

Tabla de compatibilidad ECMAScript 5

http://kangax.github.io/es5-compat-table/

Extendiendo tipos

Librerías que proporcionan cross browser polyfills para los nuevos métodos de ECMAScript 5

Simulando clases

JavaScript es un verdadero lenguaje orientado a objetos

Es facil copiar las características de un lenguaje basado en clases

Simulando clases

function Circle(radius) {
  // propiedad de instancia
  this.r = radius;
}

// propiedad de clase estática
Circle.PI = 3.14159;

// método de instancia
Circle.prototype.area = function() {
  return Circle.PI * this.r * this.r;
};

// método de clase estático
Circle.Max = function(a, b) {
  if (a.r > b.r) return a;
  else return b;
};

Simulando clases

Si queremos hacer que un miembro de la clase sea privado podemos usar closures

function ImmutableRectangle(w, h) {
  this.getWidth = function() {
    return w;
  };
  this.getHeight = function() {
    return h;
  };
}

ImmutableRectangle.prototype.area = function() {
  return this.getWidth() * this.getHeight();
};

Superclases y subclases

  • La clase Object es la más generica de todas
  • Todas las demás clases heredan de Object
  • Se crea una cadena de prototipos

Subclases

function PositionedRectangle(w, h, x, y) {
  Rectangle.call(this, w, h);

  this.x = x;
  this.y = y;
}

PositionedRectangle.prototype = extend(Rectangle.prototype);

PositionedRectangle.prototype.contains = function(x, y) {
  return (x > this.x &&
          x < this.x + this.width &&
          y > this.y &&
          y < this.y + this.height);
};

Subclases

function PositionedRectangle(w, h, x, y) {
  Rectangle.call(this, w, h);

  this.x = x;
  this.y = y;
}

PositionedRectangle.prototype = extend(Rectangle.prototype);

PositionedRectangle.prototype.constructor = PositionedRectangle;

PositionedRectangle.prototype.contains = function(x, y) {
  return (x > this.x &&
          x < this.x + this.width &&
          y > this.y &&
          y < this.y + this.height);
};

Subclases

var r = new PositionedRectangle(2, 2, 2, 2);

r instanceof PositionedRectangle; // true
r instanceof Rectangle; // true
r instanceof Object; // true

Invocar métodos sobrecargados

Rectangle.prototype.toString = function() {
  return '[' + this.width + ', ' + this.height + ']';
};

PositionedRectangle.prototype.toString = function() {
  return '(' + this.x + ', ' + this.y + ') ' +
         Rectangle.prototype.toString.call(this);
};

Mixins

  • Hacer subclases no es la única manera de extender una clase
  • Se pueden copiar los métodos de una clase a otra
function mixin(from, to) {
  var protoFrom = from.prototype;
  var protoTo = to.prototype;

  for (var name in protoFrom) {
    if (typeof protoFrom[name] !== 'function') continue;
    protoTo[name] = protoFrom[name];
  }
}

Mixins

function Colored(c) {
  this.color = c;
}

Colored.prototype.getColor = function() {
  return this.color;
};

function ColoredRectangle(h, w, c) {
  Rectangle.call(this, w, h);
  Colored.call(this, c);
}

ColoredRectangle.prototype = extend(Rectangle.prototype);
ColoredRectangle.prototype.constructor = ColoredRectangle;

mixin(Colored, ColoredRectangle);

Gracias

CSS slideshow - reveal.js

Oriol Torras / orioltorras.com