Extender tipos de datos

Categories:

Hay ocasiones en que quisiéramos que los tipos de datos básicos en JavaScript tuvieran algunas funciones extras. Una manera para resolver esto es hacer funciones y utilizar el valor o valores como parámetro.

Ejemplo

function remove(array, item) {
  if (array.indexOf(item) != -1) {
    array.splice(array.indexOf(item), 1)
  }
}

// Ejemplo de uso
var arreglo = [1,2,3,4,5] 
remove(arreglo, 3)

Otra opción sería hacer una clase, crear distintos métodos que realicen la funcionalidad que estamos buscando. Después crear un objeto, para finalmente, obtener la funcionalidad esperada. Lo malo de este acercamiento es que, dependiendo de la funcionalidad, puede resultar en más trabajo del que resuelve.

¿cómo se vería tu código si pudieras crear métodos que se pudieran utilizar directamente sobre variables o valores como si fueran métodos propios del lenguaje?

// Utilizar esto:

mi_variable.mi_metodo()
otra_variable.otro_metodo(parametro)
15..metodo_numeros()


// En lugar de: 

mi_metodo(mi_variable)
otro_metodo(otra_variable, parametro)
metodo_numeros(15)

Utilizando el concepto de prototipos es posible extender la funcionalidad de los tipos de datos de JavaScript. Al utilizarse con los tipos de datos originales (primitivas) de JavaScript, la sintaxis de uso es la misma. Dependiendo de cómo escribas tu código, es probable que sea más legible.

Extender Números

Number.prototype.write = function() {
    var valor = this.toString()
    var nombre = ''
    switch(valor) {
      case "0": 
        nombre = "cero"
        break
      case "1":
        nombre = "uno"
        break
      case "2":
        nombre = "dos"
        break
      case "3":
        nombre = "tres"
        break
      case "4":
        nombre = "cuatro"
        break
     case "5":
      nombre = "cinco"
      break
    }
    return nombre
  }
// Ejemplo *
3..write()

Extender Cadenas de Texto

String.prototype.toSnakeCase = function() {    
    return this.toLowerCase().replace(/ /g, "_")  
  }
  
  
  String.prototype.toCamelCase = function() {
    var contents = this.split(" ")
    var modified
    for (i = 0; i < contents.length; i++) {
      if (i == 0) {
        modified = contents[i].toLowerCase()
      } else {
        modified += contents[i].charAt(0).toUpperCase() + contents[i].slice(1, contents[i].length)
      }
    }
    return modified
  }

// Ejemplo

var lorem = "lorem ipsum"
lorem.toSnakeCase()
lorem.toCamelCase()

Extender Arreglos

Array.prototype.remove = function(item) {
    if (this.indexOf(item) != -1) {
      this.splice(this.indexOf(item), 1)
    }
    return this
  }
// Ejemplo
var arreglo = [1,2,3,4,5] 
arreglo.remove(3)

Referencia de uso

// Referencia de uso
<TipoDeDato>.prototype.<nombre_metodo> = function() {

}

<TipoDeDato>: Number, String, Array, Boolean
<nombre_metodo>: nombre que le quieres dar al método

// Ejemplo
Number.prototype.mi_metodo_numero = function() {
// funcionalidad
}
String.prototype.mi_metodo_texto = function() {
// funcionalidad
}
Array.prototype.mi_metodo_arreglo = function() {
// funcionalidad
}
Boolean.prototype.mi_metodo_boolean = function() {
// funcionalidad
}

Una vez que tienes toda la funcionalidad que necesitas para los distintos tipos de datos, la puedes agrupar en un archivo externo – JavaScript.extended.js – e incluirlo como primer archivo JavaScript en tus proyectos. De esta manera tienes tu versión extendida de JavaScript y el te puede ayudar a que tu código se más legible.

* Nota:
Al utilizar los métodos con números se tiene que utilizar doble punto.
JavaScript no hace distinción entre números enteros y decimales. Al utilizar un punto después de un número, JavaScript considera que el siguiente caracter tiene que ser numérico (espera que el número sea decimal). Si se manda llamar directamente el método, considera que el caracter es ilegal.

Nota:
Esta técnica se llama monkey-patching y básicamente:

“…se refiere a las modificaciones dinámicas de una clase o módulo en tiempo de ejecución, motivados por la intención de arreglar el código de terceros existente como una solución para un error o función que no actúa como lo deseas.”Monkey Patch en wikipedia (inglés)

Contraindicaciones

Si el código está escrito sin cuidado o no se encuentra documentado el monkey patch pueden surgir los siguientes problemas:

Puede crear confusión al momento de querer aplicar los métodos (que son inexistentes) como parte de la funcionalidad en otro código.

Si dos o más módulos (librerías) intentan aplicar un parche al mismo método (o crear un método con el mismo nombre) el que se encuentre al final es el que se utiliza.

Monkey patch Pitfalls wikipedia (inglés)