Должны ли arguments.slice() работать в ES5?
Я наблюдаю за Крокфордом на Javascript - акте III: функционирую в "Ultimate" около 41 минуты 26 секунд. Код на его экране использует arguments.slice()
таким образом, что вызывает ошибку для меня.
function curry(func){
var args = arguments.slice(1);
...
}
Он объясняет это так:
Сначала я получу массив аргументов, кроме первого, потому что первый - это функция, и мне она не нужна. В этом случае я предполагаю, что я на ES5, поэтому я не делаю ужасно
Array.prototype.apply()
трюк.
Проблема в том, что работает arguments.slice()
приводит к этой ошибке:
Uncaught TypeError: arguments.slice is not a function
Я тестирую современные браузеры с ES5! Единственный способ заставить код работать, если я использую некоторые "ужасные" трюки (как он их называет), например Array.prototype.slice.apply(arguments, [1])
или же [].slice.call(arguments, 1);
,
Он просто ошибается? Есть ли в его слайде опечатка? Почему не arguments.slice()
работать в моих браузерах ES5?
3 ответа
Цитируя члена TC39 Аллена Вирфса-Брока:
До очень позднего периода разработки ECMAScript 5 объект аргумента собирался наследовать все методы Array.prototype. Но "окончательный проект" ES5, одобренный TC39 в сентябре 2009 года, не имел этой функции.
Создание объекта аргументов, унаследованного от прототипа Array, планировалось на самом деле, но на практике это сломало сеть. Следовательно, он был удален из окончательной редакции перед официальной публикацией.
В настоящее время, когда стандартизирован ECMAScript 2015 (он же ES6), лучшим подходом является использование остальных параметров:
function curry(func, ...args) {
// ...
}
Что эквивалентно ES5:
function curry(func) {
var args = [].slice.call(arguments, 1);
// ...
}
Эта функция уже изначально доступна в Firefox и Edge и доступна везде, если вы используете компилятор JavaScript, такой как Babel.
Как arguments
является массивом, вы можете использовать:
function fn() {
const args = Array.from(arguments)
}
arguments
Объект не является массивом. Он похож на Array (Array like), но не имеет никаких свойств Array, кроме length
,
Сначала вам придется преобразовать его в массив, используя указанные трюки.
var slice = Array.prototype.slice;
function curry(func){
var args = slice.call(arguments, 1); // converts into array
}
аргументы собирались унаследовать все прототипные методы от массивов, но в окончательном варианте эта функция была удалена.
https://mail.mozilla.org/pipermail/es5-discuss/2009-August/003112.html
Я реализую логику, чтобы заставить объект Arguments наследовать от Array в WebKit в прошлую пятницу, и он быстро оказался серьезным
несовместимость с Prototype.js... Это нарушает как минимум ряд сайтов Apple и Nasa.gov -... Из-за этих поломок сайтов, вызванных серьезной проблемой совместимости
в довольно крупной библиотеке кажется невозможным попытаться дооснастить
поведение массива как на аргументы.
Таким образом, в конце концов, вместо того, чтобы заставлять всех менять свой код, чтобы избежать взлома веб-страниц, они отменили это изменение. Так что даже в ES5 вам все еще нужно применить вышеупомянутый трюк для преобразования аргументов в реальный массив.