Contenido

Programación Orientada a Objetos en Javascript

14 Feb

+ 6

Por definición, Javascript no es un lenguaje orientado a objetos, sinó orientado a prototipos. Esto solo significa que Javascript no diferencia entre Clases y Objetos, trata a ambos como parte de un objeto «prototipo» que sirve de base para crear los demás objetos.

A pesar de todo, existen implementaciones que nos permiten usar este paradigma o metodología con simulaciones desarrolladas en el propio lenguaje.

1) Joose-js

Joose-js, es quizás la librería más nueva que nos permite utilizar esta metodología, capaz de dotarnos de Clases, Herencia,… funcional en todos los navegadores.

Demo

// Create a class called Point
Class("Point", {
    has: {
        x: {
            is:   "rw",
            init: 0
        },
        y: {
            is:   "rw",
            init: 0
        }
    },
    methods: {
        clear: function () {
            this.setX(0);
            this.setY(0);
        }
    }
})

// Use the class
var point = new Point();
point.setX(10)
point.setY(20);
point.clear();

2) Prototype

Prototype es uno de los primeros frameworks JS que incorporaban esta posibilidad y que extendía los elementos que lo componían de esta forma.

Demo

var Animal = Class.create({
  initialize: function(name, sound) {
    this.name  = name;
    this.sound = sound;
  },

  speak: function() {
    alert(this.name + " says: " + this.sound + "!");
  }
});

// subclassing Animal
var Snake = Class.create(Animal, {
  initialize: function($super, name) {
    $super(name, 'hissssssssss');
  }
});

var ringneck = new Snake("Ringneck");
ringneck.speak();
//-> alerts "Ringneck says: hissssssssss!"

3) Base2

Base2, el framework desarrollado por Dean Edwards, es (sinó recuerdo mal) la primera implementación de este tipo en un framework JS.

Demo

var Animal = Base.extend({
  constructor: function(name) {
    this.name = name;
  },

  name: "",

  eat: function() {
    this.say("Yum!");
  },

  say: function(message) {
    alert(this.name + ": " + message);
  }
});

4) MooTools

MooTools, apareció hace 2 años (casi 3) y desde que nació apostó por esta metodología. Su código está desarrollado mediante Clases que se encargan de extender todos los objetos nativos del lenguaje.

Demo

var Cat = new Class({
    initialize: function(name){
        this.name = name;
    }
});
var myCat = new Cat('Micia');
alert(myCat.name); //alerts 'Micia'

var Cow = new Class({
    initialize: function(){
        alert('moooo');
    }
});
var Effie = new Cow($empty);

5) Simple Javascript Inheritance

John Resig publicó hace unos meses un sistema de tan solo 25 líneas para conseguir generar clases con sus respectivos objetos.

Código

(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();

Demo

var Person = Class.extend({
  init: function(isDancing){
    this.dancing = isDancing;
  }
});

var Ninja = Person.extend({
  init: function(){
          this._super( false );
  }
});

var p = new Person(true);
p.dancing; // => true

var n = new Ninja();
n.dancing; // => false

6) Class2k (osea una versión que he montado yo)

El nombre lo he puesto por poner algo, y el código lo he extraido de MooTools 1.11. Considero que es una implementación muy limpia y sin duda nos permite crear clases con sus objetos. Lo he portado para usarse con extend() y nos permite orientar a objetos nuestro código con solo 61 líneas.

Código

function extend(opt, el){
    var el = el || this;
    for (var property in opt) el[property] = opt[property];
    return el;
};	
function type(el, type){ return (el instanceof type);}

function merge(){
	var mix = {};
	for (var i = 0; i < arguments.length; i++){
		for (var property in arguments[i]){
			var ap = arguments[i][property];
			var mp = mix[property];
			if (mp && type(ap, Object) && type(mp, Object)) mix[property] = merge(mp, ap);
			else mix[property] = ap;
		}
	}
	return mix;
};

var Class = function(properties){
        var klass = function(){
            return (arguments[0] !== null && this.initialize && type(this.initialize, Function)) ? this.initialize.apply(this, arguments) : this;
        };
        extend(this, klass);
        klass.prototype = properties;
        klass.constructor = Class;
        return klass;
};

extend({
    empty: function(){},
    extend: function(properties){
        var proto = new this(null);
		var Merge = function(previous, current){
	        if (previous && previous != current){
	            if (current.constructor != previous.constructor) return current;
	            switch(current.constructor){
	                case Function:
	                    var merged = function(){
	                        this.parent = arguments.callee.parent;
	                        return current.apply(this, arguments);
	                    };
	                    merged.parent = previous;
	                    return merged;
	                case Object: return merge(previous, current);
	            }
	        }
	        return current;
	    };
        for (var property in properties){
            var pp = proto[property];
            proto[property] = Merge(pp, properties[property]);
        }
        return new Class(proto);
    },
    implement: function(){
        for (var i = 0, l = arguments.length; i < l; i++) 
			extend(arguments[i],this.prototype);
    },
}, Class.prototype);

Demo

var Animal = new Class({
	initialize: function(age){
	     this.age = age;
	}
});
var Cat = Animal.extend({
	initialize: function(name, age){
		this.parent(age); //will call the previous initialize;
		this.name = name;
	}
});
var myCat = new Cat('Micia', 20);
alert(myCat.name); //alerts 'Micia'
alert(myCat.age); //alerts 20

¿Y tu que? ¿Usas la Orientación a Objetos en tu código Javascript?

  • Interesante texto sobre programacion orientada a objetos en javascript: http://www.crockford.com/javascript/inheritance.html

  • ups!! y JQuery..

    ojala algún día lo implementen! 😀

  • Class2k basado MooTools: sabia decisión 🙂

    Por otra parte, siendo formales, tengo que discrepar contigo en el asunto de la orientación a objetos. JavaScript sí es un lenguaje de programación orientado a objetos, pero en la línea de Self: se basa en prototipos en lugar de clases. Cierto es que la mayoría de los lenguajes orientados a objetos se fundamentan en el concepto de clase, y que cuesta cierto trabajo cambiar el modelo mental con el que uno está acostumbrado a trabajar. A mí el paso de Java a JavaScript me costó mucho sufrimiento estético, pero francamente, una vez realizada la transición, no cambio por nada (mientras no me obliguen, claro) el estilo de JavaScript.

    Básicamente ya no utilizo clases, y toda la ‘jeraquización’ de objetos y funcionalidades la desarrollo a base de capturar métodos desde ‘mixins’.

  • Emm, pues tengo un poco programando orientado a objetos pero yo utilizo esto otro:

    objGato = function(nombre,color){
    this.color = color;
    this,nombre = nombre;
    }

    var pelusa = new objGato(«pelusa»,»rojo»);
    document.write(pelusa.color);

    Que tiene de diferente programar con lo anterior a lo que publicaste?

    Es que soy un poco nuevo xD

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.