2012-02-07 6 views
10

Apenas estoy comenzando JavaScript y me pregunto si hay genios que puedan ayudarme a entender esta línea por línea.¿Puede algún genio decirme qué está pasando en este pequeño código? De Secrets of the JavaScript Ninja

1: Function.prototype.bind = function(){ 
2: var fn = this, 
3:  args = Array.prototype.slice.call(arguments), 
4:  object = args.shift(); 
5: return function(){ 
6: return fn.apply(object, 
7:  args.concat(Array.prototype.slice.call(arguments))); 
8: }; 
9: }; 

Soy principiante, pero si puedes enseñarme, entonces eres increíble. Conozco los prototipos, llame, cambie, aplique un poco para poder omitir las partes para principiantes (aunque creo que no debería hacerlo, para que otros que apenas ingresan a JS puedan aprender cómo).

Aviso: Sé que hay una cierta "código similar" pidiendo una pregunta similar here pero yo estoy pidiendo línea por línea explicación y no son (no duplicados) (también se pueden saltar línea 8 & 9) :)

Respuesta

12

Esta es una implementación parcial, en EcmaScript 3, del método EcmaScript 5 bind que hace partial application. Se hace

myObject.method.bind(myObject, 1, 2)(3, 4) 

es equivalente a

myObject.method(1, 2, 3, 4) 

pero también es más conveniente porque se puede hacer

var m = myObject.method.bind(myObject, 1, 2); 
m(3, 4); 
m(5, 6); 

en lugar de

myObject.method(1, 2, 3, 4); 
myObject.method(1, 2, 5, 6); 

Nit: Los dos no son totalmente equivalente, porque si el La primera llamada al myObject.method hace this.method = somethingElse; y luego el método enlazado aún llamaría al original.

descomponerlo:

Function.prototype.bind = function(){ 

Añade un método para el tipo de función incorporado.

var fn = this, 

Tiendas this que debería ser un Function en uso por lo que se puede utilizar dentro de un cierre.

args = Array.prototype.slice.call(arguments), 

Crea una matriz que contiene los argumentos para bind.

object = args.shift(); 

elimina el primer argumento de la args y lo almacena en object. Esto se usará como el valor this para fn cuando se aplique más tarde.

return function(){ 

devuelve una función que actúa como un método parcialmente aplicada. Esta función cuando llama

return fn.apply(object, 

llama a la función a la izquierda de .bind pasar el primer argumento de bind como this. apply es un método reflexivo especial de funciones que permite invocar una función con una matriz de argumentos similar a *args o **kwargs en python, o ... en Java.

args.concat(Array.prototype.slice.call(arguments))); 

pases como argumentos a fn, los argumentos a bind seguido por el argumento para el cierre.

5

Digamos que tenemos una función

function hi(a, b) { alert('hi! '+(a+b)); } 

definir una función para cada función (lo que podría utilizar, por ejemplo, hi.bind())

1: Function.prototype.bind = function(){ 

fn es this, por lo tanto, la función original (en nuestro ejemplo this = hi)

2: var fn = this, 

arguments (argumentos de la función) no son una matriz normal, por lo que la siguiente es una técnica para convertirlo en una matriz que contiene exactamente los mismos elementos que arguments

3:  args = Array.prototype.slice.call(arguments), 

desplaza la args, volviendo el primero (que es el contexto con el que desea llamar a la función)

4:  object = args.shift(); 

esta función devuelve una nueva función

5: return function(){ 

apply es una función que permite llamar a una función con un enfoque y argumentos dados. hi(2,3) es igual a hi.apply(window, [2,3])

6:  return fn.apply(object, 

La función será llamada con los argumentos a bind y ningún argumento adicional se pasan a la función que estamos en (que bind devoluciones)

7:  args.concat(Array.prototype.slice.call(arguments))); 
8:  }; 
9: }; 

Así hi(2,3) es igual a los iguales (hi.bind(window, 2, 3))()(hi.bind(window, 2))(3)

Cuestiones relacionadas