2009-01-31 22 views
5

me encontré con un rompecabezas Javascript a preguntar: escribir una pieza de una sola línea de código JavaScript que concatena todas las cadenas pasadas en una función:
concatenación de forma recursiva a funciones JavaScript argumentos

 

    function concatenate(/*any number of strings*/) { 
     var string = /*your one line here*/ 
     return string; 
    } 
 

@meebo

Al ver que los argumentos de la función se representan como un objeto indexado QUIZÁS una matriz, pensé que se puede hacer de forma recursiva. Sin embargo, mi implementación recursiva arroja un error. - "conc.arguments.shift no es una función" -

 

    function conc(){ 
     if (conc.arguments.length === 0) 
      return ""; 
     else 
      return conc.arguments.shift() + conc(conc.arguments); 
} 
 

parece como si conc.arguments no es una matriz, pero se puede acceder por un índice de número y tiene una propiedad de longitud ??? confuso: comparta opiniones y otras implementaciones recursivas.

Gracias

Respuesta

12

argumentsis said to be un objeto Array similar. Como ya vio, puede acceder a sus elementos por índice, pero no tiene todos los métodos de Array a su disposición. Otros ejemplos de objetos tipo Array son colecciones HTML devueltas por getElementsByTagName() o getElementsByClassName(). jQuery, si alguna vez lo ha usado, también es un objeto tipo Array. Después de consultar algunos objetos DOM, inspeccione el objeto jQuery resultante con Firebug en la pestaña DOM y verá lo que quiero decir.

aquí está mi solución para el problema de Meebo:

function conc(){ 
    if (arguments.length === 0) 
     return ""; 
    else 
     return Array.prototype.slice.call(arguments).join(" "); 
} 

alert(conc("a", "b", "c")); 

Array.prototype.slice.call(arguments) es un buen truco para transformar nuestra arguments en un objeto Array verdadera. En Firefox Array.slice.call(arguments) sería suficiente, pero no funcionará en IE6 (al menos), por lo que la versión anterior es lo que generalmente se usa.Además, este truco no funciona para la colección devuelta por los métodos de DOM API en IE6 (al menos); Lanzará un Error. Por cierto, en lugar de call uno podría usar apply.

Una pequeña explicación acerca de los objetos tipo Array. En JavaScript puede usar casi cualquier cosa para nombrar a los miembros de un objeto, y los números no son una excepción. Así que es posible construir un objeto que se parece a esto, que es perfectamente válido JavaScript:

var Foo = { 
    bar : function() { 
     alert('I am bar'); 
    }, 

    0 : function() { 
     alert('I am 1'); 
    }, 

    length : 1 
} 

El objetivo anterior es un objeto Array-como por dos razones:

  1. Tiene miembros cuyos nombres son números , por lo que son como los índices de matriz
  2. tiene una propiedad length, sin la cual no se puede transformar el objeto en un auténtico arsenal con la construcción: Array.prototype.slice.call(Foo);

El objeto argumentos de un objeto Function es muy parecido al objeto Foo, solo que tiene un propósito especial.

+0

Obtengo un error de Objeto esperado en slice.call en IE –

1

La lista de argumentos no es una matriz real. Creo que puede tomar prestados los métodos de matriz y usarlos en argumentos con "llamar" o "aplicar".

7

Mozilla on the subject:

Los argumentos objeto no es una matriz. Es es similar a una matriz, pero no tiene ninguna matriz propiedades, excepto la longitud. Por ejemplo, no tiene el método pop. Sin embargo, puede ser convertido en un verdadero matriz:

var args = Array.prototype.slice.call(arguments); 

Por lo tanto la solución a su problema es bastante simple:

var string = Array.prototype.slice.call(arguments).join(""); 

Por cierto: Además, se señala:

El objeto arguments es una variable local disponible en todas las funciones ; argumentos como una propiedad de La función ya no se puede utilizar.

Sólo se debe utilizar en lugar de argumentsfunc.arguments

+0

¿Por qué hacer argumentos en una matriz real? Me pregunto qué tan rápido es el segmento ... – svinto

1

Usted puede hacer esto:

function concatenate() { 
    if (arguments.length > 1) { 
     return arguments[0] + concatenate.apply(this, Array.prototype.splice.call(arguments, 1)); 
    } 
    return arguments[0]; 
} 
6

Esto funciona:

function concatenate(){ 
    return [].join.call(arguments, ""); 
} 
alert(concatenate("one", "two", "three")); 
+0

¿Por qué no llamas a la función con 3 argumentos de cadena en lugar de 1 argumento de matriz con 3 cadenas? Eso eliminaría las comas :) Me gusta mucho esta solución. +1 –

+0

¡Porque estoy cansado y enfermo! Gracias por señalar mi estupidez, ahora funciona. – svinto

+0

¡Funciona, pero no es recursivo! – Nosredna

Cuestiones relacionadas