2011-04-09 22 views
9

Lectura a través de la fuente en: http://documentcloud.github.com/underscore/underscore.jscomportamiento subrayado con bind

Este es el método utilizado con tanta frecuencia _bind (He quitado el cheque nativa para mayor claridad)

_.bind = function(func, obj) { 
    var args = slice.call(arguments, 2); 
    return function() { 
     return func.apply(obj, args.concat(slice.call(arguments))); 
    }; 
    }; 

Los argumentos que van pasando func.apply parece innecesariamente duplicado al final

Un ejemplo utilizando intérprete nodo (quitar última línea para tratar de Firebug etc ..)

var arguments = [1,2,3,4,5,6]; 
var args = Array.prototype.slice.call(arguments, 2); 
var appliedArgs = args.concat(Array.prototype.slice.call(arguments)); 
require('sys').puts(appliedArgs); 

Este salidas:

3,4,5,6,1,2,3,4,5,6 

Dudo mucho que he encontrado un bug, pero confundido en cuanto a por qué su trabajo de esta manera, ¿por qué añadir los argumentos de nuevo de tal manera. Confundido

Respuesta

16

El método bind devuelve un cierre, que puede aceptar argumentos adicionales para pasar a la función. Las dos referencias a arguments en el código de subrayado no se refieren al mismo conjunto de argumentos. El primero es de la función adjunta, y el segundo es del cierre devuelto. Aquí es una versión ligeramente modificada de este método, que se espera hace que sea más claro:

_.bind = function(func, obj /*, arg1, arg2 ... argN */) { 

    // Prepare default arguments for currying, removing 
    // the function and object references 
    var args = Array.prototype.slice.call(arguments, 2); 

    // Return a closure that has access to the parent scope 
    return function(/* arg1, arg2 ... argN */) { 

    // Prepare arguments that are passed when bound 
    // method is called 
    var args2 = Array.prototype.slice.call(arguments); 

    // Curry the method with the arguments passed 
    // to the enclosing function and those passed 
    // to the bound method 
    return func.apply(obj, args.concat(args2)); 

    } 

Esto le permite volver de ganarse un método cuando se une a un objeto. Un ejemplo de su uso sería:

var myObj = {}, 
    myFunc = function() { 
     return Array.prototype.slice.call(arguments); 
    }; 

myObj.newFunc = _.bind(myFunc, myObj, 1, 2, 3); 

>>> myObj.newFunc(4, 5, 6); 
[1, 2, 3, 4, 5, 6] 
+0

Gracias gary. Eché de menos eso, tiene sentido ahora. –

+2

No hay problema. Si intenta hacerse una idea del código fuente de Underscore, también proporcionan una versión anotada: http://documentcloud.github.com/underscore/docs/underscore.html –

1

La llamada a _bind se une a un objeto y algunos argumentos a un método. Puede pasar argumentos adicionales al método enlazado cuando lo invoque. Probablemente no pasaría los mismos argumentos dos veces. Uso es:

function sum() { 
    var total = 0; 
    for (var i=0; i < arguments.length; ++i) { 
     total += arguments[i]; 
    } 
    return total; 
} 
var sumsome = _bind(sum, {}, 1, 2, 3); 
sumsome(4,5,6); // equivalent to the call ({summ: sum}).summ(1,2,3,4,5,6) 
sumsome('a','b','c'); // equivalent to the call ({summ: sum}).summ(1,2,3,'a','b','c')