Подтвердить что ты не робот

Почему не восьмеричный литерал как строка, отлитая от числа?

В JavaScript, почему восьмеричная строка чисел представлена ​​как десятичное число? Я могу использовать строчную строку с использованием Number() или +, почему не восьмеричный?

Например:

1000 === +"1000" // -> true
0xFF === +"0xFF" // -> true
0100 === +"0100" // -> false - +"0100" gives 100, not 64

Я знаю, что могу разбираться с parseInt("0100" [, 8]), но я хотел бы знать, почему кастинг не работает, как с шестнадцатеричными и десятичными числами.

Кроме того, кто-нибудь знает, почему восьмеричные литеры отбрасываются из ECMAScript 5th Edition в строгом режиме?

4b9b3361

Ответ 1

Я немного опаздываю на этот вопрос, но думаю, что могу дать хороший ответ.

Принятый ответ не говорит вам ничего более того, что вы на самом деле знаете, и упоминаете в самом вопросе: Number(value) работает как +value, но не как parseInt(value).

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

Почему строка восьмеричного числа приводится в виде десятичного числа?

Потому что конструктор чисел называется функцией (Number(value)) и Унарный + Оператор (+value) за кулисами использует внутреннюю операцию ToNumber. Целью этих конструкций является преобразование типа .

Когда ToNumber применяется к типу String, используется специальная грамматическая постановка, называемая StringNumericLiteral.

Это произведение может содержать только десятичные литералы и шестнадцатеричные целые литеры:

...

StrNumericLiteral :::
   StrDecimalLiteral
   HexIntegerLiteral

...

Существуют также семантические различия между этой грамматикой и грамматикой "нормального" NumericLiterals.

A StringNumericLiteral:

  • Может предшествовать и/или сопровождать пробелы и/или терминаторы строк.
  • Это десятичное число может иметь любое число ведущих 0 цифр. no восьмеричные!
  • Это десятичное значение может предшествовать + или - для указания его знака.
  • Это пустое или содержит только пробел, преобразуется в +0.

Теперь я перейду к функциям parseInt и parseFloat.

Цель этих функций, очевидно, состоит в сильном анализе , который семантически отличается от преобразования типа, например:

parseInt("20px");     // 20
parseInt("10100", 2); // 20
parseFloat("3.5GB");  // 3.5
// etc..

Стоит упомянуть, что алгоритм parseInt изменен в спецификации ECMAScript 5th Edition, он больше не интерпретирует числовое значение как восьмеричное для наличия начального нуля:

parseInt("010"); // 10, ECMAScript 5 behavior
parseInt("010"); // 8,  ECMAScript 3 behavior

Как вы можете видеть, это ввело несовместимость в поведение между реализациями ES3 и ES5 и, как всегда, рекомендуется использовать аргумент radix, чтобы избежать возможных проблем.

Теперь ваш второй вопрос:

Почему восьмеричные литералы исключаются из ECMAScript 5th Edition в строгом режиме?

На самом деле, это стремление избавиться от восьмеричных литералов происходит с 1999 года. Из грамматики NumericLiteral были удалены восьмеричные литературные произведения (OctalIntegerLiteralи OctalEscapeSequence), так как спецификация ECMAScript 3rd Edition, они могут быть включены для обратная совместимость (также в ES5) со старыми версиями стандарта.

Фактически, они включены во все основные реализации, но технически реализация, совместимая с ES3 или ES5, может не включать их, поскольку они описываются как ненормативный.

Это был первый шаг, теперь ECMAScript 5 Strict Mode полностью запрещает их.

Но почему?

Потому что они считались функцией, подверженной ошибкам, и на самом деле в прошлом они приводили к непреднамеренным или трудно улавливаемым ошибкам - так же, как та же проблема неявных восьмерик parseInt -.

Теперь, в строгом режиме, восьмеричный литерал вызовет исключение SyntaxError - в настоящее время доступно только в Firefox 4.0 Betas -.

Ответ 2

Потому что вы на самом деле не выполняете кастинг в правильном смысле (у JS нет кастинга) - он просто набирает жонглирование.

Когда у вас есть какой-либо литерал в Javascript и вводится метод, он создается за кулисами.

"foo".toUpperCase(), например, заменяется оценкой кода, который будет примерно похож на этот new String( "foo" ).toUpperCase();

Поскольку строки не могут быть оценены с помощью унарного оператора +, JS преобразует вашу строку в число - и она не использует parseInt() или parseFloat() внутренне - вы догадались - она ​​использует Number().

Итак, значение, которое вы видите, - это то, что вы увидите из возврата Number(), который не отображается предположим восьмеричные.

Ответ 3

Чтобы выяснить, почему восьмая поддержка была удалена в ES5, это главным образом потому, что для новичков или не-программистов синтаксис является неожиданным. Представьте себе вертикальное выравнивание ряда чисел (возможно, добавление), используя ведущие нули для их выравнивания, например - если ваши номера не используют 8 или 9, они будут обрабатываться как восьмеричные. Внезапно ваш код исчез в сорняках без какой-либо очевидной причины! Вот почему восьмеричная поддержка была удалена. Другой восьмеричный синтаксис может когда-нибудь быть добавлен, если он не создает такого несчастья (я думаю, что я помню, что я видел 0o755 как одну идею соломона), но на данный момент восьмеричный отсутствует.

Относительно несовместимого изменения parseInt, отмеченного в прошлых ответах: никакая реализация не сделала это изменение, и я подозреваю, что никакая реализация не сделает этого. ES5 в основном основан на реальности. Его новые функции обычно не нарушают существующий код (за исключением того, что новый код, конечно, должен заботиться о том, чтобы использовать новые функции, чтобы не нарушать существующий код как часть этого использования), который не пытается использовать новые функции. Его несовместимости в основном незначительны, или они неактуальны, поскольку реалии в реальном мире небрежно игнорируют спецификацию по причинам совместимости. Но не все несовместимости являются обоснованными: некоторые из них более желательны, чем гармонизация. Изменение к parseInt является примером желательного изменения. Он разбивает существующий код, который ожидает восьмеричного синтаксиса, без явного основания, для синтаксического анализа как восьмеричного.

В течение нескольких дней SpiderMonkey (движок Mozilla JavaScript) реализовал половинное изменение, чтобы сделать parseInt, когда вызывается из строкового кода режима, игнорирует восьмеричную и поддерживает восьмеричную, когда не вызывается из строкового кода режима. Это ближе к тому, что хочет ES5, но это явное препятствие для преобразования нестрого кода в строгий режим, вероятно, это смущает пользователя и, возможно, самое интересное для разработчиков, значит, вы не смогли реализовать parseInt в самом JavaScript (потому что в спецификации нет способа проверить строгость одной вызывающей функции), что может быть желательно в будущем (уменьшить поверхность атаки, облегчить реализацию и т.д.). Таким образом, мы сократили зависимость. (Я написал патч, чтобы сделать parseInt зависимым от вызывающего, и я просмотрел патч, чтобы его отменить, порожденный дальнейшим обсуждением после того, как мой начальный патч приземлился.) parseInt теперь соответствует ES3 снова, и данный веб-интерфейс, и что семантика ES5, вероятно, не совместима с ней, я сомневаюсь, что мы изменимся. Поэтому я сомневаюсь, что и другие изменятся. (Я также уверен, что они согласятся с нашей оценкой степени несовместимости Интернета с ES5, стремящейся запретить неявный восьмеричный синтаксис в parseInt, и, вероятно, с нашими другими причинами. Даже если бы мы изменили я "Я не уверен, что они последуют, и я подозреваю, что они были бы умны, чтобы не делать этого.)