Почему.join () не работает с аргументами функции?


почему это работает (возвращает "один, два, три"):

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

и эта работа (возвращает "список: 111"):

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

но не это (возвращает пустой):

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

что мне нужно сделать с моей переменной "аргументы", чтобы использовать .присоединяйтесь () к нему?

8 66

8 ответов:

он не работает, потому что arguments объект не является массивом, хотя и выглядит так. У него нет join способ:

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

преобразование arguments к массиву, вы можете сделать:

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

теперь join совместимость:

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

кроме того, вы можете использовать jQuery makeArray, который будет пытаться превратить "почти массивы", как arguments в массивы:

var args = $.makeArray(arguments);

вот что ссылка на Mozilla (мой любимый ресурс для такого рода вещи) говорит об этом:

The arguments объект не является массивом. Он похож на массив, но не не имеют никаких свойств массива, кроме length. Например, он не имеет метод pop. ...

The arguments объект доступен только внутри тела функции. Попытка доступ к аргументам объект вне объявление функции результаты в ошибка.

Если вы не заинтересованы в другие Array.prototype методами, и вы хотите просто использовать join, вы можете вызвать его напрямую, не преобразуя его в массив:

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

также вы можете найти полезным знать, что запятая является разделителем по умолчанию, если вы не определяете разделитель, по spec запятая будет использоваться.

просто используйте функцию утилиты jQuery makeArray

arguments - это не массив, это объект. Но, поскольку он так "массивов", вы можете позвонить служебная функция в jQuery makeArray чтобы заставить его работать:

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

что будет на выходе:

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

вы могли бы использовать это jQuery .joinObj расширение / плагин Я сделал.

как вы увидите в этой скрипке, вы можете использовать его следующим образом:

$.joinObj(args, ",");

или

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

Код Плагина:

(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);

вы можете использовать typeof, чтобы увидеть, что происходит здесь:

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

здесь вы можете видеть, что typeof возвращает "объект" в обоих случаях, но только один из объектов имеет определенную функцию соединения.

arguments - это не объект jQuery, а обычный объект JavaScript. Расширьте его, прежде чем пытаться позвонить .join(). Я думаю, вы бы написали:

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

(Я не слишком знаком с jQuery, только прототип, поэтому я надеюсь, что это не совсем фиктивно.)

Edit: это неправильно! Но в своем ответе Дуг найнер описывает то, что я пытаюсь сделать.

Я не знаю, есть ли простой способ преобразования аргументов в массив, но вы можете попробовать это:

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

на данный момент Вы не можете присоединиться к аргументам массива, потому что они не являются массивом, показано здесь

так что вы должны либо сначала превратить их в массив, как это,

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

или вот так, немного короче

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

если вы используете что-то вроде Бабель или совместимый браузер для использования функций es6, вы также можете сделать это с помощью аргументов rest.

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

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

что позволит вам делать еще более крутые вещи как

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

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