Ver Mensaje Individual
  #10 (permalink)  
Antiguo 06/02/2011, 15:55
Avatar de zerokilled
zerokilled
Javascripter
 
Fecha de Ingreso: abril-2009
Ubicación: Isla del Encanto, La Borinqueña [+>==]
Mensajes: 8.050
Antigüedad: 15 años
Puntos: 1485
con peras y manzanas; explicando las funciones apply y call

buenas...
veo que el tema de apply te trae loco desde un tema que se formulo recientemente. apply al igual que call, lo que hace es invocar una funcion como si fuese propia de otro objeto. o dicho de otro modo, call y apply cambia el propietario de la funcion por otro objeto. de modo que cada vez que en la funcion se utiliza la referencia this, dicha referencia representa el nuevo objeto. veamos un ejemplo:
Código:
var foo = {fn: function(){
console.log(this.bar); 
// console.log es una funcion de las consolas javascript para mostrar resultado en la consola ;
}, bar: true};

var boo = {bar: 'string'};
foo.fn.call(boo);
foo.fn.apply(boo);
en este ejemplo, notese que el objeto boo no contiene metodo pero tiene la propiedad bar al igual que el objeto foo. adiconalmente, notese que la funcion fn utiliza la referencia this para acceder al objeto que contiene la funcion. ahora, para invocar esa funcion como si fuese una funcion de boo, tendriamos que utilizar call o apply. si observas la consola de javascript, veras que la salida fue 'string'.

¿por qué existe dos funciones para el mismo propósito, o cual es la diferencia entre ellos? para ello, tendrias que ver la sipnosis de cada funcion.
Código:
fn.apply(object, array);
fn.call(object, arg1, ..., argN);
apply recibe dos argumentos, el objeto al cual se va aplicar la funcion y un array de valores. dicho array se tomaran como argumentos para la funcion aplicada al objeto. en contraste, call puede recibir uno o mas argumentos, siendo el primero el objeto y el resto los argumentos para la funcion aplicada al objeto.
Código:
var Rate = {
fixed: 1.07,
calc: function(value, add){
return this.fixed * value + add;
}};

var rate = {
fixed: 1.37
};

console.log(Rate.calc.call(rate, 3.14, 7));
console.log(Rate.calc.apply(rate, [2.3, 1.2]));
en este corto ejemplo, notese que el metodo calc recibe dos argumentos: value, add. al aplicar el metodo a otro objeto debemos tambien pasarle los parametros el cual lo puedes observar en call y apply.

proximo punto, ¿por que agregue dos ceros al inicio del array? como quizas sabras, splice modifica los arrays, ya sea agregar o eliminar elementos. el primer argumento de splice se refiere a partir de cual elemento del array se va a modificar, el segundo argumento es un conteo a partir del primer argumento, y los subsiguientes argumentos son los valores que se van a introducir al array. como veras, en el metodo del prototipo, la idea es restaurar el array con el original. no puedo utilizar concat porque dicho metodo no modifica el array, solo devuelve uno nuevo. adicional, tampoco puedes asignar un valor a this. o sea, ninguna de las siguientes lineas funciona.
Código:
this = this.clone.concat();
this = this.clone.slice(0, this.clone.length);
// notese que dice slice, no splice ;
la unica alternativ que me permite modificar el array original es splice o recorrer el clon con un bucle pero como el tema en particular es con splice entonces dejare a un lado el bucle. si hiciera lo siguiente me devuelve un resultado incorrecto:
Código:
this.splice(0, 0, this.clone);
// el array tendria como elemento otro array ;
// por ejemplo, [].splice(0,0, [0,1,2,3]) resultaria como ;
// [[0,1,2,3]] y lo que quiero lograr es [0,1,2,3] ;
por tanto, la solucion es hacer que splice introduzca los elementos al array. para ello me valgo de splice con apply. de modo que si no agrego al inicio los dos ceros, apply aplicaria la funcion de forma similar a lo siguiente.
Código:
this.clone = [0,1,2,3]; // asumiendo que dicho array es la copia ;
this.splice.apply(this, this.clone);
// la linea anterior seria similar a ;
this.splice(0,1,2,3);
notese el problema de la ultima linea, los primeros dos elementos del array estarian indicando a splice que debe comenzar por el primer elemento del array original y va a remover un solo elemento del original. el tercer argumento en adelante vendrian siendo los valores a introducir al array. por tanto, el resultado final en un array vacio seria [2,3]. ahi es donde juega el papel importante de los ceros introducidos al clon. es para que splice pueda introucir correctamente los valores del clon en el array original.

como observacion adicional, call no era apropiado en la solucion porque como iba a enumerar los argumentos a partir del array. de modo que apply hace esa tarea por mi.

hasta aqui llega la leccion de hoy...
saludos!
__________________
la maldad es una virtud humana,
y la espiritualidad es la lucha del hombre contra su maldad.

Última edición por zerokilled; 06/02/2011 a las 16:27 Razón: agregando enlace al tema