Сталкивались ли вы с ситуацией, когда вам нужно преобразовать строковый литерал в определенной системе счисления в целое число или число в десятичной системе, и наоборот. В этой статье я рассмотрю использование parseInt()
и toString()
методов в JavaScript для достижения этих преобразований, а также некоторые интересные случаи и исключения.
Начнем с parseInt
- parseInt
принимает строковый литерал в качестве первого аргумента, а второй аргумент (основание) сообщает, в какой системе счисления находится строковый литерал (8-октальное, 16-шестнадцатеричное, 2-двоичное…).
- Он всегда возвращает целое число или NaN в зависимости от допустимости строкового литерала, соответствующего основанию системы счисления.
- Что, если основание системы счисления не указано? Предполагается, что это 10
в соответствии со спецификацией ECMAScript 5, за некоторыми исключениями, которые мы обсудим ниже.
Хорошо. Теперь вы знаете, что он делает. Начнем с простых примеров и нескольких интересных случаев.
parseInt(‘100’, 10) //returns 100 parseInt(‘100’, 2) //returns 4 parseInt(‘100’, 8) //returns 64 parseInt(‘100’, 16) //returns 256
Выше приведены очевидные случаи преобразования числа 100 в различных системах счисления в целое число.
parseInt('215', 2) // returns NaN as there is no 2 in binary system parseInt('H85', 10) //returns NaN as there are no characters in decimal system parseInt('85EX',10) // returns 85 ignoring the characters after the first invalid character parseInt('32',8) // returns 26 parseInt('329',8) // returns 26, parses till 32 and ignores 9
Что можно сделать из вышесказанного?
- Во-первых, функция возвращает NaN, если первый символ строкового литерала не является символом в указанной системе счисления.
- Во-вторых, если первый символ - действительный, он анализирует строку до тех пор, пока не обнаружит недопустимый символ, а остальные усекает.
parseInt('0xff') //returns 255 parseInt('0xff',16) //returns 255 parseInt('021') //returns 21 parseInt('021',8) //returns 17 parseInt(021) //returns 17 parseInt(021,8) //returns 15
Помните, я говорил вам, что когда основание системы счисления не указано, предполагается, что оно равно 10
за некоторыми исключениями. Ну вот и те.
В ECMAScript 5 указано:
Если основание системы счисления не определено или0
, предполагается, что оно равно10
, кроме случаев, когда число начинается с пар символов0x
или0X
, и в этом случае предполагается, что основание системы счисления равно 16.
Итак, первые два утверждения ясны. А как насчет остальных?
Я знаю, что это сбивает с толку. Мне потребовалось некоторое время, чтобы придумать теорию, чтобы выяснить, что происходит.
До ES5 предполагалось, что строковые литералы, начинающиеся с 0
, должны быть восьмеричными, так же как и те, которые начинаются с 0x
, являются шестнадцатеричными. Но в ES5 предполагается, что это 10
. Но, думаю, это относится только к строковым литералам. Итак, когда первый аргумент не является строкой, функция parseInt считает, что он находится в восьмеричной системе, и преобразует его в строку, используя метод toString()
, передавая 8
как основание в метод toString()
. Это объясняет, почему передача 021
в качестве аргумента функции parseInt без указанного основания возвращает 17
. Что происходит при указании основания 8
. Он снова преобразует его, предполагая, что преобразованное число изначально находится в восьмеричной системе.
Звучит довольно запутанно, правда? Это только для восьмеричной интерпретации. Чтобы понять более четко, вставьте следующие утверждения один за другим в консоль разработчика и попытайтесь угадать ответ, прежде чем нажимать клавишу ВВОД.
parseInt('74') //pretty straightforward parseInt('74',10) //Not much difficulty here parseInt('074') //Easy one parseInt('074', 10) //No surprises parseInt('0X74') //Notice the prefix 0X parseInt(0X74) //any different from the above answer? parseInt('74', 16) //just another representation parseInt('74', 8) //as you expected parseInt(074) //Now, you should be starting to understand parseInt(074, 8) //Isn't it similar to parseInt(parseInt('74', 8), 8) parseInt(074,16) //Another interesting case. Should return the same value as parseInt(parseInt('74', 8), 16)
Ну .. это о parseInt
. Посмотрим, что может предложить toString()
.
toString()
при вызове числа является противоположностью parseInt, то есть он преобразует десятичную дробь в любую систему счисления от 2 до 36.
(21).toString(2) //"10101" (21).toString(8) //"25" (21).toString(16) //"15" 0x21.toString() //"33" 021.toString() //"17" (octal representation)
На Object.prototype
доступен toString()
метод. Этот метод может быть переопределен любым настраиваемым объектом, и когда он не переопределен, он возвращает строку "[Object type]”
, где type
- тип объекта.
function Vehicle (wheels, color) { this.wheels = wheels; this.color = color; } Vehicle.prototype.toString=function(){ return "overridden string value" } let car = new Vehicle(4,'blue'); car.toString() //returns "overridden string value"
Помните, что метод parseInt внутренне вызывает toString()
метод для первого переданного аргумента. Что, если вы передадите пользовательский объект в parseInt. Давай посмотрим что происходит.
function Random () { } Random.prototype.toString = function(){ return 11111; } let obj = new Random(); parseInt(obj,2) // returns 31
Как указывалось ранее, метод toString()
при вызове любого объекта наследует метод Object
, если не переопределен, что помогает определить тип объекта. Приведенные ниже утверждения и примеры взяты из документации MDN.
let toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
Я надеюсь, что осознание того, как работают toString()
и parseInt()
, позволит вам использовать их возможности и преобразовать числовой или строковый литерал из одной системы счисления в другую, а также легко применить остальные варианты их использования.
Спасибо, что прочитали это !! Надеюсь, сегодня вы узнали что-то новое.