2011-12-16 21 views
8

Estaba intentando hacer que mi código fuera más pequeño con las funciones de caché en las variables. Por ejemplo:"el objeto no es una función" cuando se guarda function.call en una variable

function test(){ 
    var a = Array.prototype.slice, 
    b = a.call(arguments); 
    // Do something 
    setTimeout(function(){ 
    var c = a.call(arguments); 
    // Do something else 
    }, 200); 
} 

Así que en lugar de llamar Array.prototype.slice.call(arguments), puedo hacer a.call(arguments);.

Estaba tratando de hacer esto aún más pequeño al almacenar en caché Array.prototype.slice.call, pero eso no estaba funcionando.

function test(){ 
    var a = Array.prototype.slice.call, 
    b = a(arguments); 
    // Do something 
    setTimeout(function(){ 
    var c = a(arguments); 
    // Do something else 
    }, 200); 
} 

Esto me da TypeError: object is not a function. ¿Porqué es eso?

typeof Array.prototype.slice.call devuelve "function", como se esperaba.

¿Por qué no puedo guardar .call en una variable (y luego llamarla)?

+0

que motor de JavaScript le ha dado este error? –

+0

posible duplicado de [¿Cómo hace referencia a Array.prototype.slice.call()?] (Http://stackoverflow.com/questions/6835315/how-do-you-reference-array-prototype-slice-call) – pimvdb

+0

@DanD .: Chrome 16. –

Respuesta

7

Function.prototype.call es una función ordinaria que opera sobre la función pasa como this.

Cuando llama a call desde una variable, this se convierte en window, que no es una función.
tiene que escribir call.call(slice, someArray, arg1, arg2)

+0

Limpio, eso funciona. 'var a = Array.prototype.slice, b = a.call; b.call (a, argumentos) '. Entonces, ¿hay alguna manera de "enlazar" 'esto' al copiar' .call'? –

+2

@Rocket: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind – SLaks

+0

Entonces, 'var a = Array.prototype.slice.call.bind (Array.prototype.slice)'?Editar: ¡Wow, eso realmente funciona! Editar 2: De acuerdo con la página 'var slice = Function.prototype.call.bind (Array.prototype.slice);' también funciona! ¡Ordenado! –

5

Prueba esto:

function test(){ 
    var a = function(args){ 
     return Array.prototype.slice.call(args); 
    }; 
    b = a(arguments); 
    // Do something 
    setTimeout(function(){ 
    var c = a(arguments); 
    // Do something else 
    }, 200); 
} 

El mismo error ocurrirá si se intenta hacer algo como:

var log = console.log; 
log("Hello"); 

La razón es que cuando se hace esto está asignando la función x (en mi ejemplo log) a la variable log. PERO la función contiene una llamada a this que se refiere ahora a window y no a console, que a continuación emite un error que this is not an object

+0

Weird, 'var log = console.log; log ('a'); 'da' TypeError: invocación ilegal' en Chrome 16, pero 'var logX = console.log.bind (consola); logX ('a'); 'funciona :-P –

4

El problema es que es un método call (una función que pertenece a un objeto) que se espera que su propietario (su this) sea una función. Cuando escribe a = Array.prototype.slice.call, está copiando la función, pero no el propietario.

El mensaje "el objeto no es una función" no dice que a no es una función, sino que dice que this no es una función. Técnicamente puedes lograr lo que describes escribiendo a.call(Array.prototype.slice, arguments), ¡pero obviamente eso no es lo que quieres!

+0

Cool, 'a.call (Array.prototype.slice, arguments)' en realidad funciona. Pensé que cuando copiaras una función, 'this' sería referenciado correctamente. –

+2

@Rocket: No, no puede ser, porque tenemos que ser capaces de hacer algo como 'a.foo = b.foo' o' A.prototype.foo = B.prototype.foo' o lo que sea copiar un método de un objeto a otro. ¡Sería terriblemente confuso si una llamada a 'a.foo()' operara 'b' en lugar de' a'! – ruakh

Cuestiones relacionadas