2010-01-19 14 views
62

¿Por qué este trabajo (devuelve "uno, dos, tres"):¿Por qué no funciona .join() con argumentos de función?

var words = ['one', 'two', 'three']; 
$("#main").append('<p>' + words.join(", ") + '</p>'); 

y este trabajo (devuelve "la lista: 111"):

var displayIt = function() { 
    return 'the list: ' + arguments[0]; 
} 
$("#main").append('<p>' + displayIt('111', '222', '333') + '</p>'); 

pero no esto (rendimientos en blanco):

var displayIt = function() { 
    return 'the list: ' + arguments.join(","); 
} 
$("#main").append('<p>' + displayIt('111', '222', '333') + '</p>'); 

¿Qué tengo que hacer para mi "argumentos" de variable a utilizar .join() sobre ella?

+0

Ver: http://stackoverflow.com/questions/1424710/why-is-my-join-on-a-javascript- fallo de matriz – Shog9

+0

He modificado mi respuesta para tener en cuenta su pregunta actualizada, específicamente, "¿qué tengo que hacer para que esto funcione?" parte. –

Respuesta

80

No funciona porque el objeto arguments no es una matriz, aunque parece que sí. No tiene join método:

>>> var d = function() { return '[' + arguments.join(",") + ']'; } 
>>> d("a", "b", "c") 
TypeError: arguments.join is not a function 

Para convertir arguments a una matriz, que puede hacer:

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

ahora join funcionará:

>>> var d = function() { 
    var args = Array.prototype.slice.call(arguments); 
    return '[' + args.join(",") + ']'; 
} 
>>> d("a", "b", "c"); 
"[a,b,c]" 

Como alternativa, se puede usar jQuery de makeArray, que intentará convertir "casi-matrices" como arguments en matrices:

var args = $.makeArray(arguments); 

Aquí es lo que el Mozilla reference (mi recurso favorito para este tipo de cosas) tiene que decir al respecto:

The arguments object is not an array. It is similar to an array, but does not have any array properties except length . For example, it does not have the pop method. ...

The arguments object is available only within a function body. Attempting to access the arguments object outside a function declaration results in an error.

+3

o 'Array.join (arguments,", ")' (como 'Array.forEach (arguments, func);') – Anonymous

+0

¿Qué sucede cuando uno de tus argumentos es un objeto? – user1876508

+3

@Anonymous TypeError: Object function Array() {[native code]} no tiene el método 'join' – drAlberT

0

arguments no es un objeto jQuery, solo un objeto JavaScript normal. Extiéndalo antes de intentar llamar al .join(). Creo que iba a escribir:

return 'the list:' + $(arguments)[0]; 

(No estoy muy familiarizado con jQuery, único prototipo, así que espero que esto no es completamente falso.)

Editar: Está mal! Pero en su respuesta, Doug Neiner describe lo que estoy tratando de lograr.

+2

Esto no es del todo correcto; 'arguments' no es una matriz. En cambio, es un "objeto tipo array". –

+0

Una matriz JS normal admite 'join'. –

+0

si argumentos no es una matriz, ¿cómo es que los argumentos [0] y los argumentos [1] me dan los valores correctos pasados ​​a la función? –

2

sólo tiene que utilizar la función de utilidad jQuery makeArray

arguments no es una matriz, es un objeto. Pero, puesto que tan "tipo array", puede llamar a la función de utilidad jQuery makeArray para hacer que funcione:

var displayIt = function() { 
    return 'the list: ' + $.makeArray(arguments).join(","); 
} 
$("#main").append('<p>' + displayIt('111', '222', '333') + '</p>'); 

Cuál sería:

<p>the list: 111,222,333</p> 
1

Usted puede utilizar typeof para ver lo que está pasando aquí:

>>> typeof(['one', 'two', 'three']) 
"object" 
>>> typeof(['one', 'two', 'three'].join) 
"function" 
>>> typeof(arguments) 
"object" 
>>> typeof(arguments.join) 
"undefined" 

aquí se puede ver que los rendimientos typeof "objeto" en ambos casos, pero sólo uno de los objetos tiene una función definida unirse.

19

Si usted no está interesado en otros Array.prototype métodos, y desea utilizar simplemente join, se puede invocar directamente, sin necesidad de convertirlo a un arreglo:

var displayIt = function() { 
    return 'the list: ' + Array.prototype.join.call(arguments, ','); 
}; 

También le puede resultar útil para saber que la coma es el separador predeterminado, si no define un separador, por spec se usará la coma.

+0

+1 Esta es la respuesta más rápida y segura * SI * lo único que desea es llamar a join en lugar de crear una nueva matriz. Llamar a slice para unir asignará memoria cuando la unión funcione también en objetos tipo array. – Ajax

0

No sé si hay una forma sencilla de convertir argumentos en una matriz, pero se puede intentar esto:

var toreturn = "the list:"; 
for(i = 0; i < arguments.length; i++) 
{ 
    if(i != 0) { toreturn += ", "; } 
    toreturn += arguments[i]; 
} 
2

Usted podría utilizar esta jQuery .joinObj Extension/Plugin hice.

Como se verá en ese violín, que se puede utilizar de la siguiente manera:

$.joinObj(args, ","); 

o

$.(args).joinObj(","); 

Código Plugin:

(function(c){c.joinObj||(c.extend({joinObj:function(a,d){var b="";if("string"===typeof d)for(x in a)switch(typeof a[x]){case "function":break;case "object":var e=c.joinObj(a[x],d);e!=__proto__&&(b+=""!=b?d+e:e);break;default:"selector"!=x&&"context"!=x&&"length"!=x&&"jquery"!=x&&(b+=""!=b?d+a[x]:a[x])}return b}}),c.fn.extend({joinObj:function(a){return"object"===typeof this&&"string"===typeof a?c.joinObj(this,a):c(this)}}))})(jQuery); 
+2

y ... ¿por qué el -1? este es un enchufe funcional que hace exactamente lo que se le pide? – SpYk3HH

+3

lo odio también, cuando la gente -1 mi publicación sin explicación ... +1 para ti .. T^T – Kokizzu

0

Al momento en que no puedes unir los argumentos de la matriz, porque no son matriz, shown here

lo que tiene que sea primero convertirlos en una serie como esta,

function f() { 
    var args = Array.prototype.slice.call(arguments, f.length); 
    return 'the list: ' + args.join(','); 
} 

o así, un poco más corto

function displayIt() { 
    return 'the list: ' + [].join.call(arguments, ','); 
} 

si está utilizando algo así como babel o un navegador compatible para usar las características de es6, también puede hacer esto usando argumentos de descanso.

function displayIt(...args) { 
    return 'the list: ' + args.join(','); 
} 

displayIt('111', '222', '333'); 

cuales le permiten hacer las cosas aún más genial como

function displayIt(start, glue, ...args) { 
    return start + args.join(glue); 
} 

displayIt('the start: ', '111', '222', '333', ','); 
Cuestiones relacionadas