Funciones nativas de Javascript

Miguel Sanchez
Mar 19, 2017 · 5 min read

Javascript se esta convirtiendo en el lenguaje de programación más popular, pese a ser un lenguaje relativamente fácil de utilizar, la comprensión de su funcionamiento interno no lo es tanto. Utilizar este lenguaje en un paradigma de programación orientada a objetos o incluso funcional puede convertirse en un reto.

Por eso vamos a abordar algunas de las funciones nativas de javascript para arrojar algo de luz.

En este articulo nos centraremos en las siguientes funciones:

  • Call/Apply
  • Bind
  • Map
  • Filter

Antes de prestar atención a cada una de ellas vamos a recordar el comportamiento del scoping en javascript:

“this” y “arguments”

El scoping (conocido tambien como contexto o alcance) en javascript esta basado en funciones, variables y métodos están contenidos en esta función. El objeto “this” hace referencia a la propia función y se puede utilizar de varias maneras por ejemplo, puede estar ligado al objeto “window”:

this.globalVar = {
myGlobalVarsMethod: function() { // Implementacion
}
};

console.log(this.globalVar); // { myGlobalVarsMethod: [Function] }

Y las variables pueden estar ligadas a la función que las contiene:

this.variableGlobal = 'variableGlobal';function funcionGlobal() {
this.variableInterna = 'variableInterna';
console.log(this.variableGlobal == undefined); // true
console.log(this.variableInterna 'variableInterna'); // true
return {
funcionInterna: function() {
console.log(this.variableGlobal == undefined); // true
console.log(this.variableInterna == undefined); // true
}
}
}
funcionGlobal().funcionInterna();

Hay diferentes objetos “this” ligados a la función que los invoca,
usando strict mode evitamos encontrarnos con errores si las variables no estan definidas

this.variableGlobal = 'variableGlobal';function nonStrictFunctionTest() {
return function() {
console.log(this.variableGlobal); // undefined
}
}
function strictFunctionTest() {
'use strict'; // Strict Mode
return function() {
console.log(this.variableGlobal); // TypeError: Cannot read property 'variableGlobal' of undefined
}
}
nonStrictFunctionTest()();
strictFunctionTest()();

Muchos desarrolladores desconocen que hay un objeto “arguments” dentro de cualquier función. Es similar a un array con tres propiedades principales, el destinatario de la llamada , la longitud, y la función que llama.

A continuación mostramos el objeto arguments:

function fn() {
console.log(typeof arguments); // [object Object] console.log(arguments[0]); // Iron Islands
console.log(arguments[1]); // Dorne
arguments.push("Casterly Rock"); // TypeError: undefined is not a function
var arguments = "Juego de tronos";
console.log(arguments[5]); // undefined
}
fn("Iron Islands", "Dorne");

Call/Apply

Tanto Call como Apply son utilizados para invocar un método en un objeto. Como se describió anteriormente, cada función mantiene un alcance específico en el que se define. Por lo tanto, se debe tener en cuenta el alcance de la función cuando se invoca en el objeto.

fun.apply(thisArg, [argsArray]) fun.call(thisArg[, arg1[, arg2[, ...]]])

Pasando como argumento explicitamente thisArg, la función que invoca puede acceder o modificar objetos en el contexto . El siguiente ejemplo aclara el uso de Call.

this.emblema = 'ninguno';
var robb = {
familia: 'Stark',
emblema: 'Lobo huargo'
};
var printEmblema = function() {
console.log(this.emblema);
}
printEmblema() // ninguno
printEmblema.call(robb); // Lobo huargo
printEmblema.apply(robb); // Lobo huargo

La principal diferencia entre el uso de call y apply es su notación. “Call” requiere una lista explícita de argumentos pasados separados por comas, mientras que “apply” requiere un array con los argumentos. Utilizar Apply sería pues más adecuado cuando no sabemos el número de argumentos.

Bind

Bind se utiliza para invocar métodos cuando se especifica el objeto this. Al igual que con call y apply se tiene en cuenta el scope o alcance. Es útil para cuando se necesita para enlazar un objeto a una función .

Su sintaxis es:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

Básicamente, estamos tomando la función fun y pasando thisArg como parámetro. En esencia, cada vez que se llama a “this “en la funcion fun, se está refiriendo a thisArg. Vamos a echar un vistazo más de cerca con un ejemplo sencillo:

var robbStark = {
madre: 'Catelyn',
padre: 'Eddard'.
}
var getPadre = function() {
console.log(this.padre);
}
getPadre(); // undefined
getPadre.bind(robbStark)(); // Eddard
getPadre(robbStark); // undefined

El primer getPadre() devuelve undefined porque el atributo padre no se configura en esta. Entonces ¿qué es this? Es el objeto de la ventana global ya que no esta establecido explicitamente. El segundo getPadre() devuelve “Edd Stark”, porque el getPadre de robbStark es this. Muchos desarrolladores de Java / C ++ asumirían que el último getPadre() devolvería el resultado deseado — aunque una vez más, estaría ligado al “this” global.

Aquí está la implementación de bind:

Function.prototype.bind = function(scope) {
var _that = this;
return function() {
return _that.apply(scope, arguments);
}
}

Como consecuencia de la sintaxis del scope en Javascript, el objeto this de la función de retorno es diferente al de bind. Por lo tanto, “_that” se establece en este “this” para mantener el entorno correcto. De lo contrario, this.apply(scope, arguments) sería indefinido.

Map

la función mapa de Javascript es una técnica de programación funcional para iterar sobre un array, para realizar operaciones sobre cada elemento devolviendo un array con los elementos modificados . Aunque si los elementos son objetos (no primitivos), las buenas prácticas nos dicen que clonar el objeto que alterar el original.

Su sintaxis es:

arr.map(callback[, thisArg])

El método de devolución de llamada tiene tres parámetros: CurrentValue, índice, y la matriz.

Aquí vemos un ejemplo simple:

function Personaje(nombre) {
this.nombre = nombre;
}
var tyrion = new Personaje('Tyrion');
var joffrey = new Personaje('Joffrey');
var margaery = new Personaje('Margaery');
var personajes = [tyrion, joffrey, margaery];
var casas = ['Lannister', 'Baratheon', 'Tyrell'];
var nombreDePersonajes = personajes.map(function(currentValue, index, array) {
var personajeClon = (JSON.parse(JSON.stringify(currentValue))) // Clone currentValue
personajeClon.nombre = currentValue.nombre + " " + casas[index];
return personajeClon;
});
nombreDePersonajes.map(function(currentValue) {
console.log(currentValue.nombre);
}); /** Output: Tyrion Lannister Joffrey Baratheon Margaery Tyrell */

Habiendo comprendido lo que hace un mapa, veamos su implementación

Array.prototype.map = function(fun, thisArg) {
if (typeof fun != 'function') {
throw new Error("The first argument must be of type function");
}
var arr = [];
thisArg = (thisArg) ? thisArg : this;
thisArg.forEach(function(element) {
arr[arr.length] = fun.call(thisArgs, element);
});
return arr;
}

Filter

El método filter también se utiliza para tratar arrays. Al igual que en el mapa, el filtro devuelve una nueva matriz y acepta una función y un thisArg opcional. Sin embargo, la matriz devuelta contiene sólo los elementos que se ajustan a una determinada condición probada en la función retorno de la llamada. Esta función debe devolver un valor lógico.
Ésta es la sintaxis de filter:

arr.filter(callback[, thisArg])

Una vez más, thisArg es opcional y la función de devolución de llamada acepta tres parámetros, el valor actual ,el índice, y el array.

function Persona(nombre, familia) {
this.nombre = nombre;
this.familia = familia;
}
var cersei = new Persona('Cersei', 'Lannister');
var daenerys = new Persona('Daenerys', 'Targaryen');
var arya = new Persona('Arya', 'Stark');
var personas = [cersei, daenerys, arya];
var casaStark = personas.filter(function(currentValue, index, array) {
return currentValue.familia == 'Stark';
}).map(function(currentValue) {
console.log(currentValue.nombre + " de la casa " + currentValue.familia + ".");
}); /** Output: Arya de la casa Stark. */

Por último, echemos un vistazo a la implementación de la función filter:

Array.prototype.filter = function(fun, thisArg) {
if (typeof fun !== 'function') {
throw new Error("The first argument must be of type function");
}
var arr = [];
thisArg = (thisArg) ? thisArg : this;
thisArg.forEach(function(element) {
if (fun.call(thisArg, element)) {
arr[arr.length] = element;
}
});
return arr;
};

Conclusión

Hay muchas más funciones nativas nos pueden ser útiles, pero, por experiencia, éstas resultan ser las más confusas.

Esperamos que este artículo os de una idea de partes internas de Javascript y aclare algunos de sus puntos más confusos. Call, Apply, y Bind son difíciles de comprender, aunque todo resulta mas fácil con la práctica. Prueba a utilizar map y filter siempre que sea posible, evitando así las técnicas tradicionales de bucle.

Codeine Labs

Codeine Labs is an independent development studio based in the UK, where professionals around the world work together to get the best results.

Miguel Sanchez

Written by

Codeine Labs

Codeine Labs is an independent development studio based in the UK, where professionals around the world work together to get the best results.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade