Вопрос

Я наткнулся на следующий код:

var f = function () {
    var args = Array.prototype.slice.call(arguments).splice(1);

    // some more code 
};

В принципе, результат в args является массивом , который является копией arguments без своего первого элемента.

Но чего я точно не могу понять, так это почему f's arguments (который является объектом, который содержит введенные аргументы функции в объект, подобный массиву) объект передается в slice метод и каким образом slice(1) удаляет первый элемент (расположенный с индексом 0).

Кто-нибудь, пожалуйста, может объяснить это для меня?

P.S.Код взят из этого частичная прикладная функция

Это было полезно?

Решение

<Note>
Фактический код из этого связанный ответ является:

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

т. е."нарезать", а не "сращивать"
</Note>

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

var a = ['a', 'b', 'c'];
var b = a.slice();  // b is now a copy of a
var c = a.slice(1); // c is now ['b', 'c']

Итак, короткий ответ заключается в том, что код в основном эмулирует:

arguments.slice(1); // discard 1st argument, gimme the rest

Однако вы не можете сделать это напрямую.В особенный arguments объект (доступно внутри контекста выполнения всех функций JavaScript), хотя Array-Нравится в том смысле, что он поддерживает индексацию через [] оператор с цифровыми клавишами на самом деле не является массивом;Ты не можешь .push на это, .pop выключите его, или .slice это и т.д.

Способ, которым код выполняет это, заключается в "обмане" slice функция (которая опять же недоступна на arguments объект) для запуска в контексте arguments, через Function.prototype.call:

Array.prototype.slice // get a reference to the slice method
                      // available on all Arrays, then...
  .call(              // call it, ...
    arguments,        // making "this" point to arguments inside slice, and...
    1                 // pass 1 to slice as the first argument
  )

Array.prototype.slice.call(arguments).splice(1) выполняет то же самое, но выполняет посторонний вызов splice(1), который удаляет элементы из массива, возвращенные из Array.prototype.slice.call(arguments) начиная с индекса 1 и продолжается до конца массива. splice(1) не работает в IE (технически отсутствует 2-й параметр, указывающий, сколько элементов для удаления требуется IE и ECMAScript).

Другие советы

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

Сначала берется копия arguments(*), затем удаляет из него все элементы, кроме первого (нестандартным способом), и присваивает удаляемые элементы args.

Дополнительный массив, который создается, затем изменяется и выбрасывается, является совершенно избыточным.Было бы лучше сказать — поскольку версия в ответе, на который вы ссылались, действительно делает:

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

Частичное функциональное применение также является особенностью function.bind метод, стандартизированный пятым изданием ECMAScript.Пока браузеры не внедрили это, вы можете выбрать резервную версию JS-native в нижней части этот ответ.

*: array.slice() является обычной идиомой для копирования массива, и array.slice(1) за то, что взял за хвост.Он должен быть вызван явно через Array.prototype потому что arguments не является массивом, даже если он выглядит точно так же, как один, поэтому не имеет обычных методов массива.Это еще одна из странных ошибок JavaScript.

Вы довольно часто видите людей, использующих Array.prototype методы для объектов, которые не являются массивами;стандарт третьей редакции ECMAScript делает все возможное, чтобы сказать, что это нормально делать для arguments похожий на массив, но не что вы также можете сделать это с другими подобными массивам объектами, которые могут быть объектами хоста, такими как NodeList или HTMLCollection.Хотя тебе может сойти с рук звонок Array.prototype методы в не-массиве во многих современных браузерах единственное место, где это действительно безопасно делать, - это arguments.

Возвращаемое значение соединения представляет собой массив элементов, которые были удалены, но исходный массив (или массивоподобный объект) усекается по индексу соединения.

Создание копии с помощью slice сохраняет исходный массив arguments, предположительно для последующего использования в функции.

В этом случае тот же результат может быть получен с args = [].slice.call(arguments, 1)

function handleArguments(){
 var A= [].slice.call(arguments).splice(1);
 //arguments is unchanged
 var s= 'A='+A+'\narguments.length='+arguments.length;

 var B= [].splice.call(arguments, 1);
 // arguments now contains only the first parameter
 s+= '\n\nB='+B+'\narguments.length='+arguments.length;
 return s;
}

// test
alert(handleArguments(1, 2, 3, 4));

returned value:
//var A= [].slice.call(arguments).splice(1);
A=2,3,4
arguments.length=4

//var B= [].splice.call(arguments, 1);
B=2,3,4
arguments.length=1
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top