Что мешает современной реализации Javascript не рассматривать аргументы как реальный массив?

Я думаю, что это старое поведение Javascript (Крокфорд сказал, что это ошибка проектирования), что внутри функции, arguments похож на массив, за исключением того, что он не является реальным массивом, поэтому методы массива не могут быть вызваны на нем:

function foo() { console.log(arguments.slice(1)) }   // won't work
foo(1,2,3);

И я только что попробовал это на последнем Firefox и Chrome, и он не будет работать на обоих. Таким образом, мы можем использовать

function foo() { console.log(Array.prototype.slice.call(arguments, 1)) }
foo(1,2,3);

Но почему бы не сделать arguments реальный массив в современном JavaScript? Вероятно, не должно быть какой-либо программы, которая зависит от arguments не будучи реальным массивом? В чем может быть причина, чтобы не делать это настоящим массивом сейчас?

Одна из причин, по которой я могу придумать, заключается в том, что если программисты начнут рассматривать его как массив, то код не будет работать в старых браузерах, но в ECMA-5 есть и другие вещи, которые не будут работать и в старых браузерах.

5 ответов

До очень позднего периода разработки ECMAScript 5 объект аргумента собирался наследовать все методы Array.prototype. Но "окончательный проект" ES5, одобренный TC39 в сентябре 2009 года, не имел этой функции.

В августе 2009 года Оливер Хант из Apple опубликовал это в списке рассылки es5-обсудить

https://mail.mozilla.org/pipermail/es5-discuss/2009-August/003112.html

Я реализую логику, чтобы заставить объект Arguments наследовать от Array в WebKit в прошлую пятницу, и он быстро оказался серьезным
несовместимость с Prototype.js... Это нарушает как минимум ряд сайтов Apple и Nasa.gov -... Из-за этих поломок сайтов, вызванных серьезной проблемой совместимости
в довольно крупной библиотеке кажется невозможным попытаться дооснастить
поведение массива как на аргументы.

Остальная часть TC39 согласилась с оценкой Оливера, и эта функция была удалена из окончательного варианта.

Возможно, такой код достаточно исчез из сети, чтобы предлагаемое решение ES5 работало сегодня. Однако это не имеет значения, потому что параметры отдыха в ES6 - лучшее решение проблемы и совершенно новая синтаксическая функция, которая не может иметь проблем с обратной совместимостью с существующим кодом.

Есть сайты в Интернете, которые полагаются на arguments не являющийся массивом, например, использующий более старые версии Prototype и script.aculo.us. Это означает, что любой браузер, который его изменил (ES4 включил это, и он был реализован вместе со многими другими частями в Futhark, используемом в Opera с 9.5–10.10), сломал бы эти сайты, и существует сильное поощрение рынка, чтобы не ломать сайты (любые браузер, который ломает сайты, не будет использоваться пользователями, которые заботятся об этих сайтах по понятным причинам, поскольку многие сайты редко обновляются).

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

Если это был массив, то он должен быть массивом только для чтения, что означает, что мы должны избавиться от push, pop, splice и т. Д. Любого метода, который модифицирует массив. К этому моменту, хотя я согласен, что другие методы, такие как slice, могут пригодиться, но это уже структура данных, которая имеет другие требования, чем массив JavaScript.

Я думаю, что они не должны были говорить, что это массивоподобный объект, на мой взгляд, это просто другой объект, который, как оказалось, имеет свойство length (то же самое, что и Array).

В следующей версии ECMAScript эта проблема (и несколько других) решается с помощью остальных параметров.

function foo(...rest) {
    console.log(rest.slice(1))
}

foo(1, 2, 3);

В отличие от arguments, остальные параметры будут реальными массивами, так что это будет работать.

Остальные параметры могут сделать еще больше. В приведенном выше примере вы, вероятно, хотели использовать первый аргумент для одного, а все, что за ним, для чего-то другого. Вы могли бы сделать это вместо этого:

function foo(first, ...rest) {
    console.log('first: ', first);
    console.log('rest: ', rest);
}

foo(1, 2, 3);

Это войдет:

первый: 1

отдых: [ 2, 3 ]

Предложение: http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters

что мешает современной реализации не рассматривать аргументы как реальный массив?

Реализации чего? Спецификация EcmaScript 5.1, да. Тем не менее, достаточно точно указано, что должно быть arguments обязательный и что такое Arguments Объект есть.

Кроме того, Arguments объект просто ненастоящий Array, так как он имеет очень особенное поведение в отношении своих свойств. [[Get]], [[Delete]] и т. Д. Перезаписываются для отражения переменных аргумента функции. призвание push, splice и т. д. на такой объект, если бы это был массив, может привести к хаосу

Другие вопросы по тегам