OOP: Instanciación funcional e instanciación pseudoclásica

Diego Villa
Nowports Tech and Product
4 min readNov 17, 2020

En esta publicación, discutiremos cómo crear objetos en JavaScript. Exploraremos el enfoque tradicional utilizando la instanciación de clase pseudoclásica y terminaremos con la instanciación de clase introducida en ECMAScript 6.

Introducción a los objetos

Los objetos son pares llave/valor para almacenar información sobre una entidad que podemos representar en nuestro código. Crea un objeto usando las llaves {} y nos permite agregar propiedades y métodos usando la notación de punto.

let employee = {};// Properties
employee.name = 'Diego';
employee.position = 'Software Engineer';
// Methods
employee.program = function () {
console.log(`${this.name} is programming!`);
};
employee.program(); // Result: Diego is programming!

Creación de objetos usando funciones

Para crear varios objetos usamos una función constructora. Una función de constructor encapsula la creación de un objeto y le permite crear múltiples instancias de la misma estructura de objeto.

La creación de una función de constructor para crear instancias de nuevos objetos sigue el patrón de instanciación funcional.

function Employee(name, position) {
let employee = {};

employee.name = name;
employee.position = position;
employee.program = function() {
console.log(`${this.name} is programming!`);
};
return employee;
}
const employeeDiego = Employee('Diego', 'Software Engineer');
const employeeJuan = Employee('Juan', 'Sofware Architect');

Instanciación funcional con métodos compartidos

Cada vez que creamos una nueva instancia del objeto Employee, estamos creando, en la memoria, algo como esto:

const employeeDiego = {
name: 'Diego',
position: 'Software Engineer',
program: [Function],
};
const employeeJuan = {
name: 'Juan',
position: 'Software Architect',
program: [Function],
};

Podemos observar que creamos dos objetos que comparten la misma funcionalidad (program). Como son solo dos, no vemos el impacto en el uso de memoria; pero si creamos miles, la desperdiciamos repitiendo la misma funcionalidad. Para evitar este problema, usaremos la instanciación funcional con métodos compartidos.

const employeeMethods = {
program: function() {
console.log(`${this.name} is programming!`);
}
};
function Employee(name, position) {
let employee = {};

employee.name = name;
employee.position = position;
employee.program = employeeMethods.program;

return employee;
}
const employeeDiego = Employee('Diego', 'Software Engineer');
const employeeJuan = Employee('Juan', 'Sofware Architect');

Con esta mejora estaremos creando, en memoria, algo como esto:

const employeeDiego = {
name: 'Diego',
position: 'Software Engineer',
program: [Function: program],
};
const employeeJuan = {
name: 'Juan',
position: 'Software Architect',
program: [Function: program],
};

En JS, los objetos se pasan como referencia, por lo que solo hemos creado un único objeto que encapsula la función del programa. Cada instancia del objeto Employee accede a la misma función en la memoria.

Object.create

Podemos mejorar nuestra función de constructora usando Object.create.

const employeeMethods = {
program: function() {
console.log(`${this.name} is progamming`);
}
};
function Employee(name, position) {
let employee = Object.create(employeeMethods);

employee.name = name;
employee.position = position;
return employee;
}
const employeeDiego = Employee('Diego', 'Software Engineer');
const employeeJuan = Employee('Juan', 'Sofware Architect');

Con esta mejora, cada vez que creamos una nueva instancia del objeto Employee tendremos, en la memoria, algo como esto:

const employeeDiego = {
name: 'Diego',
position: 'Software Engineer',
};
const employeeJuan = {
name: 'Juan',
position: 'Software Architect',
};

Si los objetos creados no tienen el método del program, ¿cómo será posible invocarlo? Como utilizamos Object.create(employeeMethods) cada vez que invocamos employee.program() el método no será encontrado, pero lo buscará en el objecto principal (employeeMethods).

Creación de instancias de prototipos

En JavaScript, cada función tiene una propiedad prototype que hace referencia a un objeto. Esta propiedad nos permite compartir métodos en todas las instancias de una función.

function Employee(name, position) {
let employee = Object.create(employeeMethods);

employee.name = name;
employee.position = position;
return employee;
}
console.log(Employee.prototype); // Employee {}

Entonces, usamos la propiedad prototype para compartir la función program en todas las instancias, en lugar de usar un objeto separado.

function Employee(name, position) {
let employee = Object.create(Employee.prototype);
employee.name = name;
employee.position = position;
}
Employee.prototype.program = function () {
console.log(`${this.name} is programming`);
};
const employeeDiego = Employee('Diego', 'Software Engineer');

Con esta mejora, cada vez que creamos una nueva instancia del objeto Employee tendremos, en la memoria, algo como esto:

const employeeDiego = {
name: 'Diego',
position: 'Software Engineer',
};

Y el prototype de Employee será algo como:

{
program: [Function]
}

Creación de instancias de clase pseudoclásica

Actualmente, estamos usando la función Object.create() para crear un nuevo objeto basado en el prototype de un objeto principal y luego devolvemos ese objeto creado. Utilizando new, podemos fusionar Object.create() y devolver la funcionalidad. Accedemos al objeto creado usando this.

function Employee(name, position) {
this.name = name;
this.position = position;
}
Employee.prototype.program = function () {
console.log(`${this.name} is programming`);
};
const employeeDiego = new Employee('Diego', 'Software Engineer');

Este patrón se denomina instanciación de clase pseudoclásica. Cuando usamos new estamos invocando el constructor de la función. Si no agregamos new, la función no creará el objeto y devolverá undefined.

Instanciación de clase

En ECMAScript 6 se agregó class, para crear clases de forma similar a lenguajes como Java. La palabra class no cambia la funcionalidad interna para la creación de una clase; en realidad es una mejora de sintaxis para hacer un código más ameno.

class Employee {
constructor(name, position) {
this.name = name;
this.position = position;
}
program() {
console.log(`${this.name} is programming!`);
}
}
const employeeDiego = new Employee('Diego', 'Software Engineer');

--

--

Diego Villa
Nowports Tech and Product

Software Engineer @nowports. ITC’18 — @TecdeMonterrey.