Я знаю, что это используется, чтобы сделать аргументы реальным массивом, но я не понимаю, что происходит при использовании Array.prototype.slice.call(arguments)
474
Я знаю, что это используется, чтобы сделать аргументы реальным массивом, но я не понимаю, что происходит при использовании Array.prototype.slice.call(arguments)
Ответы:
Что происходит под капотом, так это то, что, когда
.slice()
вызывается нормально,this
это массив, а затем он просто перебирает этот массив и выполняет свою работу.Как
this
в.slice()
функции массива? Потому что, когда вы делаете:...
object
автоматически становится значениемthis
вmethod()
. Итак, с:...
[1,2,3]
Массив устанавливается как значениеthis
в.slice()
.Но что, если вы могли бы заменить что-то еще в качестве
this
значения? Пока все, что вы заменяете, имеет числовое.length
свойство и кучу свойств, которые являются числовыми индексами, оно должно работать. Этот тип объекта часто называют массивоподобным объектом ..call()
И.apply()
методы позволяют вручную установить значениеthis
в функции. Так что, если мы устанавливаем значениеthis
в.slice()
на массив типа объекта ,.slice()
просто предположим , он работает с массивом, и сделаем свое дело.Возьмите этот простой объект в качестве примера.
Это, очевидно, не массив, но если вы можете установить его в качестве
this
значения.slice()
, то он просто будет работать, потому что он достаточно похож на массив для.slice()
правильной работы.Пример: http://jsfiddle.net/wSvkv/
Как вы можете видеть в консоли, результат - это то, что мы ожидаем:
Так вот что происходит, когда вы устанавливаете
arguments
объект в качествеthis
значения.slice()
. Потому чтоarguments
имеет.length
свойство и кучу числовых индексов,.slice()
просто работает так, как если бы он работал над реальным массивом.источник
Array.prototype.slice
описание метода.for-in
утверждение не гарантирует порядок. Используемый алгоритм.slice()
определяет числовой порядок, начинающийся с0
и заканчивающийся (не включительно) с.length
указанным объектом (или массивом или чем-то еще). Таким образом, порядок гарантированно будет согласованным во всех реализациях.var obj = {2:"two", 0:"zero", 1: "one"}
. Если мы используемfor-in
для перечисления объекта, нет гарантии порядка. Но если мы используемfor
, мы можем вручную следить за соблюдением порядка:for (var i = 0; i < 3; i++) { console.log(obj[i]); }
. Теперь мы знаем, что свойства объекта будут достигнуты в порядке возрастания чисел, который мы определили в нашемfor
цикле. Вот что.slice()
делает. Это не волнует, если у него есть фактический массив. Это только начинается в0
и обращается к свойствам в восходящем цикле.arguments
Объект не является на самом деле экземпляр массива, и не имеет какого - либо из методов массива. Таким образом,arguments.slice(...)
не будет работать, потому что объект arguments не имеет метода slice.Массивы действительно имеют этот метод, и поскольку
arguments
объект очень похож на массив, они совместимы. Это означает, что мы можем использовать методы массива с объектом arguments. А поскольку методы массивов были созданы с учетом массивов, они будут возвращать массивы, а не другие объекты аргументов.Так зачем использовать
Array.prototype
? ЭтоArray
объект, для которого мы создаем новые массивы из (new Array()
), и этим новым массивам передаются методы и свойства, такие как slice. Эти методы хранятся в[Class].prototype
объекте. Таким образом, для эффективности вместо доступа к методу слайса с помощью(new Array()).slice.call()
или[].slice.call()
, мы просто получаем его прямо из прототипа. Это так, нам не нужно инициализировать новый массив.Но почему мы должны делать это в первую очередь? Ну, как вы сказали, он преобразует объект аргументов в экземпляр Array. Однако причина, по которой мы используем слайс, - это скорее взлом, чем что-либо другое. Метод среза примет, как вы уже догадались, срез массива и вернет этот срез в качестве нового массива. Передача ему без аргументов (кроме объекта arguments в качестве его контекста) заставляет метод slice взять полный кусок переданного «массива» (в данном случае объект arguments) и вернуть его как новый массив.
источник
Обычно звонит
скопирует массив
a
вb
. Тем не менее, мы не можем сделатьпотому что
arguments
не является реальным массивом, и не имеетslice
в качестве метода.Array.prototype.slice
являетсяslice
функцией для массивов, иcall
запускает функцию сthis
установленным наarguments
.источник
prototype
? неslice
нативныйArray
метод?Array
это функция конструктора, и соответствующий «класс» этоArray.prototype
. Вы также можете использовать[].slice
slice
это метод каждогоArray
экземпляра, но неArray
функция конструктора. Вы используетеprototype
для доступа к методам теоретических экземпляров конструктора.Во-первых, вы должны прочитать, как работает вызов функций в JavaScript . Я подозреваю, что одного достаточно, чтобы ответить на ваш вопрос. Но вот краткое изложение того, что происходит:
Array.prototype.slice
извлекает метод из «s прототипа . Но вызов его напрямую не сработает, так как это метод (а не функция)slice
Array
и поэтому ему необходим контекст (вызывающий объектthis
), в противном случае он будет выброшенUncaught TypeError: Array.prototype.slice called on null or undefined
.call()
Метод позволяет определить контекст метода, в основном делает эти два вызова эквивалентны:За исключением первого требует, чтобы
slice
метод существовал вsomeObject
цепочке прототипов России (как он это делаетArray
), тогда как последний позволяет контексту (someObject
) быть переданным методу вручную.Кроме того, последнее сокращение от:
Который так же, как:
источник
источник
Array.prototype.slice.call (arguments) - это старомодный способ преобразования аргументов в массив.
В ECMAScript 2015 вы можете использовать Array.from или оператор распространения:
источник
Это потому, что, как отмечает MDN
Здесь мы обращаемся
slice
к нативному объекту,Array
а не к его реализации, и поэтому дополнительный.prototype
источник
Не забывайте, что низкоуровневые основы этого поведения - приведение типов, полностью интегрированное в JS-движок.
Slice просто берет объект (благодаря существующему свойству arguments.length) и возвращает массив-объект, приведенный после выполнения всех операций над ним.
Те же логики, которые вы можете проверить, если попытаетесь обработать String-метод значением INT:
И это объясняет утверждение выше.
источник
Он использует
slice
массивы методов и вызывает егоthis
какarguments
объект. Это означает , что она называет его , как если бы тыarguments.slice()
при условии ,arguments
у есть такой метод.Создание среза без каких-либо аргументов просто займет все элементы - поэтому он просто копирует элементы
arguments
в массив.источник
Предположим, у вас есть:
function.apply(thisArg, argArray )
Метод slice () выбирает часть массива и возвращает новый массив.
Поэтому, когда вы вызываете
Array.prototype.slice.apply(arguments, [0])
метод среза массива, вызывается (bind) для аргументов.источник
Может быть, немного поздно, но ответ на весь этот беспорядок в том, что call () используется в JS для наследования. Если мы сравним это, например, с Python или PHP, то call используется соответственно как super (). init () или parent :: _ construct ().
Это пример его использования, который проясняет все:
Ссылка: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance
источник
когда .slice () вызывается нормально, это массив, а затем он просто перебирает этот массив и выполняет свою работу.
источник
Я просто пишу это, чтобы напомнить себе ...
Или просто используйте эту удобную функцию $ A, чтобы превратить большинство вещей в массив.
пример использования ...
источник