Преобразование и приведение типов | JavaScript Camp
Приведение типов (type coercion)
Это автоматическое или неявное преобразование значений из одного типа данных в другой (например, строки в число). Преобразование типа похоже на приведение типа, потому что они оба преобразуют значения из одного типа данных в другой с одним ключевым🗝️ различием — приведение типа является неявным, тогда как преобразование типа может быть неявным или явным.
Примеры 👇 :
function learnJavaScript() { const value1 = ‘5’ const value2 = 9 let sum = value1 + value2 return sum }
Loading…
В приведённом выше примере JavaScript приводит число 9
в строку, а затем объединяет два 2️⃣ значения вместе, в результате получается строка 59
. JavaScript имел выбор между строкой или числом и решил использовать строку.
Компилятор мог привести строку 5
к числу и вернуть сумму 14
, но он этого не сделал. Чтобы получить этот результат, вам нужно явно преобразовать строку 5
в число, используя метод Number()
👇 :
function learnJavaScript() { const value1 = ‘5’ const value2 = 9 let sum = Number(value1) + value2 return sum }
Loading…
Видео
Преобразование типов (type conversion)
Означает передачу данных из одного типа данных в другой. Неявное преобразование происходит, когда компилятор автоматически присваивает (назначает) типы данных, но исходный код📟 также может явно требовать преобразования для завершения.
Строковое преобразование
Строковое преобразование происходит, когда требуется представление чего-либо в виде строки. Например, мы можем использовать функцию String(value)
, чтобы преобразовать значение к строке 👇 :
function learnJavaScript() { let value = true // boolean value = String(value) return typeof value }
Loading…
Преобразование происходит очевидным образом. true
✅ становится "true"
✅
Численное преобразование
Численное преобразование происходит в математических функциях⚙️ и выражениях.
function learnJavaScript() { let value = ‘6’ / ‘2’ return value }
Loading…
Мы можем использовать функцию Number(value)
, чтобы явно преобразовать value
к числу 👇 :
function learnJavaScript() { let str = ‘123’ let num = Number(str) return typeof num }
Loading. ..
Явное преобразование часто применяется, когда мы ожидаем получить число из строкового контекста, например из текстовых 📜 полей форм.
Если строка не может быть явно приведена к числу, то результатом преобразования будет NaN
(англ. Not-a-Number, «не число»). Например 👇:
function learnJavaScript() { let age = Number(‘Любая строка вместо числа’) return age }
Loading…
Правила численного преобразования:
Значение | Преобразуется в… |
---|---|
undefined | NaN |
null | 0 |
true / false | 1 / 0 |
string | Пробельные символы по краям обрезаются. Далее, если остаётся пустая строка, то получаем 0, иначе из непустой строки «считывается» число. При ошибке🙅♂️ результат NaN. |
Примеры:
Number(' 123 ') // 123
Number('123z') // NaN (ошибка чтения числа на месте символа "z")
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
Учтите, что null
и undefined
ведут себя по-разному. Так, null
становится нулём, тогда как undefined
приводится к NaN
.
Логическое преобразование
Логическое преобразование самое простое. Происходит в логических операциях, но также может быть выполнено явно с помощью функции⚙️ Boolean(value)
.
Правила логического преобразования:
Значения, которые интуитивно «пустые», вроде 0
, пустой строки, null
, undefined
и NaN
, становятся false
. Все остальные значения становятся true
.
Boolean(1) // true
Boolean(0) // false
Boolean('Привет!') // true
Boolean('') // false
Более короткий способ функкции Boolean
двойное НЕ(!!) используют для преобразования значений к логическому типу:
!!'non-empty string' // true
!!null // false
То есть первое НЕ преобразует значение в логическое значение и возвращает обратное, а второе НЕ снова инвертирует его. В конце мы имеем простое преобразование значения в логическое.
Заметим, что строчка с нулём «0» — это true
Некоторые языки👅 (к примеру, PHP) воспринимают строку "0"
как false
. Но в JavaScript, если строка не пустая, то она всегда true
Boolean('0') // true
Boolean(' ') // пробел это тоже true (любая непустая строка это true)
Проблемы?
Пишите в Discord или телеграмм чат, а также подписывайтесь на наши новости
Вопросы:
Какую функцию нужно использовать для строкового преобразования?
Boolean(value)
String(value)
Number(value)
Что такое приведение типов?
- Передача данных из одного типа в другой
- Преобразование значений из одного типа данных в другой
- Представление чего-либо в виде строки
Какое ключевое различие между приведением типов и преобразованием типов?
- Приведение типа явное, а преобразование типа неявное
- Приведение типа неявное, а преобразование типа явное
- Приведение типа неявное, а преобразование типа может быть и явным и неявным
В каком случае результатом преобразования будет NaN
?
- Когда строка не может быть явно приведена к числу
- Когда число не может быть явно приведено к строке
- Когда в коде есть ошибка
Чем становятся «пустые» значения при преобразовании?
null
true
false
Для того чтобы понять, на сколько вы усвоили этот урок, пройдите тест в мобильном приложении нашей школы по этой теме или в нашем телеграм боте.
Ссылки:
- MDN web docs — Приведение типов
- для подростков: прекрасное руководство по программированию для начинающих, том 1: Javascript — Jeremy Moritz
- JavaScript.ru
- Арифметические действия с целыми числами
Contributors ✨
Thanks goes to these wonderful people (emoji key):
Dmitriy Vasilev 📖💵 | Resoner2005 🐛 🎨 🖋 |
Преобразование типов в JavaScript | by Serj Bulavyk
Know your engines!
Перевод статьи Alexey Samoshkin “JavaScript type coercion explained”.
Преобразование типов это процесс конвертации значения из одного типа в другой (как например, строки в число, объекта к булевому значению и т. д.). Любой тип, будь то примитив или объект, может быть преобразован в другой тип. Для справки, примитивы это: number
, string
, boolean
, null
, undefined
+ Symbol
(добавлен в ES6).
В качестве примера преобразования типов, можно ознакомиться с JavaScript Comparison Table, где продемонстрировано как ведёт себя оператор нестрогого сравнения ==
для разных типов a
и b
.
Из-за побочного эффекта оператора ==
в виде неявного приведения типа, эта матрица выглядит довольно пугающей, и запомнить все эти комбинации не представляется возможным. К счастью, вам не обязательно это делать, достаточно просто знать принципы, которые лежат в основе преобразования типов.
Эта статья подробно расскажет вам о том, как работает механизм преобразования типов в JavaScript и вооружит вас необходимыми знаниями для того, что-бы вы могли самостоятельно объяснить как вычисляются и каков будет результат следующих выражений. В конце статьи я продемонстрирую ответы и объясню их.
true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == ‘x’
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0
Этот список скорее представляет собой те вещи, которые вам как программисту делать не стоит, а поэтому расценивайте этот список как своеобразные упражнения, для того чтобы оценить насколько хорошо вы знаете механизм приведения типов. Если вам станет скучно, вы можете найти больше примеров на wtfjs.com.
Кстати, иногда вы можете встретить подобные вопросы на собеседованиях на позицию JavaScript разработчика. Итак, поехали дальше 🙂
Явное и неявное преобразование
Преобразование типов может происходить явно и неявно.
Когда разработчик хочет намеренно произвести преобразование типов, написав, к примеру Number(value)
, это называется явным преобразованием типов (или type casting).
Так как JavaScript это слабо типизированный язык, преобразование между разными типами может происходить автоматически, и это называется неявным преобразованием типов. Чаще всего это происходит когда вы применяете операторы к значениям разных типов, таких как 1 == null
, 2 / `5`
, null + new Date()
, может происходить в зависимости от контекста, как например, в случае с if (value) {…}
, где value будет приведено к булевому значению.
Оператор строгого равенства ===
не приводит к неявному преобразованию типов. Оператор нестрогого равенства ==
, в свою очередь, производит сравнение операндов и, если требуется, неявное преобразование типов.
Неявное преобразование типов — это палка о двух концах: с одной стороны это источник проблем и разочарований, а с другой — механизм, который позволяет нам писать меньше кода, не теряя при этом читабельности.
Три типа конвертации
Во-первых, следует знать, что в JavaScript существует всего 3 типа преобразования:
- строковое
- булевое
- численное
Во-вторых, логика преобразования для примитивов и объектов работает по-разному, но, и примитивы и объекты могут быть преобразованы только этими тремя способами.
Давайте сначала разберёмся с примитивами.
Приведение к строке
Для явного приведения значения к строке необходимо применить к нему функцию String()
. Неявное преобразование будет вызвано бинарным оператором +
, кода один из операндов является строкой:
String(123) // explicit
123 + '' // implicit
Все примитивы будут приведены к строке вполне естественно, как вы могли и ожидать:
String(123) // '123'
String(-12. 3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
Преобразование символов происходит немного сложнее, потому что они могут быть преобразованы только явным образом. Вы можете прочитать об этих правилах подробнее здесь.
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown
Булевое преобразование
Для явного преобразования к булевому значению, нужно применить функцию Boolean()
. Неявное преобразование происходит в логическом контексте if (val) { … }
или при применении логических операторов (||
&&
!
).
Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator
На заметку, логические операторы такие как ||
и &&
производят булевое преобразование под капотом, но при этом всегда возвращают оригинальное значение операндов, даже если они не являются булевыми.
// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123
Поскольку существует всего два возможных результата преобразования, легче просто запомнить список ложных значений:
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false
Любое значение, которое не вошло в этот список, будет преобразовано в true
, включая объекты, функции, Array
, Date
и так далее. Символы, пустые объекты и массивы так же будут иметь значение true
.
Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true
Численное преобразование
Для явного преобразования к числу нужно применить функцию Number()
, точно так же, как мы делали с Boolean()
и String()
. ~
)
-
+
*
/
%
). Обратите внимание, что бинарный оператор +
не вызывает численного преобразования, если один из операндов является строкой+
==
(включая !=
). Обратите внимание, что данный оператор не вызывает численное преобразование, если оба операнда являются строкамиNumber('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit
Примеры того, как примитивы будут преобразованы в числа:
Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12. 34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123
При преобразовании строки в число, движок сначала отсекает все пробельные символы, символы \n
, и \t
в начале и в конце строки, и возвращает NaN
если обрезанная строка не представляет из себя корректное число. Если строка окажется пустой, то результатом будет 0
.
null
и undefined
обрабатываются по разному: null
станет 0
, в то время как undefined
станет NaN
.
Численное преобразование, как явное так и неявное, не работает для символов. Более того, движок бросает ошибку TypeError
, вместо того, чтобы по-тихому преобразовать Symbol
в NaN
, как это происходит с undefined
. Подробнее о правилах преобразования символов можно посмотреть на MDN.
Number(Symbol('my symbol')) // TypeError is thrown
+Symbol('123') // TypeError is thrown
Существует два специальных правила которые следует запомнить:
- При применении
==
кnull
илиundefined
, численное преобразование не происходит, так какnull
может равняться толькоnull
илиundefined
, и ничему другому.
null == 0 // false, null is not converted to 0
null == null // true
undefined == undefined // true
null == undefined // true
2. NaN
не равен ничему, даже самому себе.
if (value !== value) { console.log("we're dealing with NaN here") }
Преобразование типов для объектов
До текущего момента мы рассматривали преобразования для примитивов, что является достаточно банальным.
Когда дело доходит до объектов, и движок встречает выражение вроде [1] + [2, 3]
, ему сначала необходимо привести объекты к примитивным значениям, а уже потом выполнить финальное преобразование. Как и в случае с примитивами, объект может быть преобразован всего тремя способами: численным, строковым, булевым.
Самый простой пример это булевое преобразование — любое не примитивное значение всегда приводится к true
, включая пустые объекты и массивы.
Объекты приводятся к примитивам посредством вызова внутреннего метода [[ToPrimitive]]
, который отвечает как за численное, так и за строковое преобразование.
Вот псевдокод реализации метода [[ToPrimitive ]]
:
Методу [[ToPrimitive]]
передаётся два аргумента: входящее значение и предпочтительный тип для преобразования: Number
или String
. Второй аргумент является опциональным.
Как для строкового так и для численного преобразования используются два метода объекта: valueOf
и toString
. Оба метода объявлены в Object.prototype
, а значит доступны для всех производных типов, таких как Date
, Array
и т.д.
В общих чертах алгоритм выглядит следующим образом:
- Если входящее значение уже является примитивом, ничего не делать и просто вернуть его.
- Вызвать
input.toString()
, если результат примитив — вернуть его. - Вызвать
input.valueOf()
, если результат примитив — вернуть его. - Если ни один из методов не вернул примитив — бросить ошибку
TypeError
.
При численном преобразовании сначала вызывается метод valueOf()
, а уже затем toString()
. При строковом преобразовании наоборот — сначала происходит вызов toString()
, а уже потом valueOf()
.
Большинство встроенных типов не имеют метода valueOf
или же имеют valueOf
, который возвращает свой собственный объект this
, который игнорируется, так как this
не является примитивом. Вот почему численное и строковое преобразование в большинстве случаев работает одинаково — оба в конечном итоге вызывают метод toString()
.
Разные операторы могут вызывают строковое или численное преобразование при помощи параметра preferredType
. Но существует два исключения: нестрогое равенство ==
и бинарный оператор +
, которые вызывают режим преобразования по умолчанию (preferredType
не указан или равен default
). В таком случае, большинство встроенных типов подразумевают численное преобразование, за исключением Date
, который предпочитает строковое преобразование.
Вот пример преобразования Date
:
Вы можете переопределить методы toString()
и valueOf()
для того, чтобы повлиять на логику преобразования объектов в примитив.
Обратите внимание, как obj + ‘’
возвращает строку 101
. Оператор +
вызывает преобразование в режиме по умолчанию, и как упоминалось выше, Object
подразумевает численное преобразование в таком случае, используя сначала метод valueOf()
, а затем уже toString()
.
Метод ES6 Symbol.toPrimitive
В ES5 вы можете повлиять на логику преобразования объекта в примитив, переопределив методы toString()
и valueOf()
.
В ES6 вы можете пойти дальше и полностью заменить внутреннюю процедуру метода [[ToPrimitive]]
, реализовав метод [Symbol.toPrimitive]()
у объекта.
Примеры
Вооружившись теорией, давайте вернёмся к нашим примерам:
true + false // 1
12 / "6" // 2
"number" + 15 + 3 // 'number153'
15 + 3 + "number" // '18number'
[1] > null // true
"foo" + + "bar" // 'fooNaN'
'true' == true // false
false == 'false' // false
null == '' // false
!!"false" == !!"true" // true
['x'] == 'x' // true
[] + null + 1 // 'null1'
[1,2,3] == [1,2,3] // false
{}+[]+{}+[1] // '0[object Object]1'
!+[]+[]+![] // 'truefalse'
new Date(0) - 0 // 0
new Date(0) + 0 // 'Thu Jan 01 1970 02:00:00(EET)0'
Ниже представлен детальный разбор того, как вычисляется каждое из выражений.
Бинарный оператор +
вызывает численное преобразование для true
и false
:
true + false
==> 1 + 0
==> 1
Оператор деления /
вызывает численное преобразование строки 6
:
12 / '6'
==> 12 / 6
==>> 2
Оператор +
выполняется слева направо, поэтому сначала выполнится выражение “number” + 15
. Поскольку один из операндов это строка, оператор +
вызовет строковое преобразование числа 15
и последующую конкатенацию двух строк. На следующем этапе выражение “number15” + 3
выполнится таким же образом.
“number” + 15 + 3
==> "number15" + 3
==> "number153"
Сначала выполняется сложение чисел 15 + 3
. На данном этапе никакого преобразования не нужно, так как оба операнда являются числами. Затем выполняется выражение 18 + ‘number’
, и так как один из операндов является строкой, то вызывается строковое преобразование для числа 18
, и последующая конкатенация двух строк.
15 + 3 + "number"
==> 18 + "number"
==> "18number"
Оператор сравнения >
вызывает численное преобразование для [1]
и null
[1] > null
==> '1' > 0
==> 1 > 0
==> true
Унарный оператор +
имеет более высокий приоритет чем бинарный оператор +
. Поэтому выражение + 'bar'
выполняется первым. Унарный плюс вызывает численное преобразования строки bar
. Так как эта строка не представляет собой корректное число, результатом будет NaN
. Следующим шагом выполнится выражение 'foo' + NaN
.
"foo" + + "bar"
==> "foo" + (+"bar")
==> "foo" + NaN
==> "fooNaN"
Оператор сравнения ==
вызывает численное преобразование, поэтому строка true
конвертируется в NaN
, а правый операнд true
станет 1
.
'true' == true
==> NaN == 1
==> falsefalse == 'false'
==> 0 == NaN
==> false
Оператор ==
обычно вызывает численное преобразование, но не в случае с null
. Действует исключение из правил: null
равен только null
или undefined
и ничему другому.
null == ''
==> false
Оператор !!
конвертирует строки true
и false
в булевое значение true
, так как это не пустые строки. А дальше оператор ==
просто сравнивает два булевых значения безо всяких преобразований.
!!"false" == !!"true"
==> true == true
==> true
Оператор ==
вызывает численное преобразование для массива. Метод массива valueOf()
возвращает сам массив, а значит результат игнорируется, так как не является примитивом. Далее, вызывается метод массива toString()
, который конвертирует [‘x’]
в строку ‘x’
.
['x'] == 'x'
==> 'x' == 'x'
==> true
Оператор +
вызывает численное преобразование массива. Метод массива valueOf()
вернёт сам массив, поэтому результат игнорируется, поскольку не является примитивом.
Далее выполняется выражение ’’ + null + 1
.
[] + null + 1
==> '' + null + 1
==> 'null' + 1
==> 'null1'
Логические операторы ||
и &&
преобразовывают операнды к булевому значению, но всегда возвращают оригинальное значение операнда (не булевое). 0
станет false
, а поскольку 0
является не пустой строкой, то конвертируется в true
. {}
пустой объект тоже становится true
.
0 || "0" && {}
==> (0 || "0") && {}
==> (false || true) && true // internally
==> "0" && {}
==> true && true // internally
==> {}
В данном примере никакого преобразования не требуется, потому что оба операнда одного типа. Так как оператор ==
сравнивает объекты по ссылке, а не по значению, а данные массивы являются двумя разными экземплярами, результатом будет false
.
[1,2,3] == [1,2,3]
==> false
Все операнды являются не примитивами, поэтому +
вызывает численное преобразование. Методы Object.valueOf()
и Array.valueOf()
возвращают самих себя, соответственно будут проигнорированы. В качестве запасного варианта, вызывается метод toString()
. Трюк в том, что первый {}
воспринимается движком не как создание объекта, а как объявление пустого блока кода и поэтому игнорируется. Выполнение начинается с выражения +[]
, которое преобразуется в пустую строку посредством метода toString()
, и далее в 0
.
{}+[]+{}+[1]
==> +[]+{}+[1]
==> 0 + {} + [1]
==> 0 + '[object Object]' + [1]
==> '0[object Object]' + [1]
==> '0[object Object]' + '1'
==> '0[object Object]1'
Данный пример лучше объяснить пошагово с точки зрения приоритета выполнения операторов:
!+[]+[]+![]
==> (!+[]) + [] + (![])
==> !0 + [] + false
==> true + [] + false
==> true + '' + false
==> 'truefalse'
Оператор -
вызывает численное преобразование для объекта Date
. Date.valueOf()
возвращает количество миллисекунд прошедших с начала Unix эпохи (в данном случае 0
).
new Date(0) - 0
==> 0 - 0
==> 0
Оператор +
вызывает преобразование по умолчанию. Date
, как исключение, подразумевает строковое преобразование, поэтому используется метод toString()
, а не valueOf()
.
new Date(0) + 0
==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)' + 0
==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'
Источники
Я бы хотел порекомендовать отличную книгу “Understanding ES6” написанную Nicholas C. Zakascholas. Книга является отличным ресурсом для изучения ES6 с достаточным уровнем освещения: не слишком поверхностно, и в тоже время не погружается в механику работы движка черезчур.
Ещё одна отличная книга, на этот раз по ES5 — SpeakingJS написанная Axel Rauschmayer.
Современный учебник Javascript — https://learn.javascript.ru/,
в особенности эти две страницы, посвящённые преобразованию типов.
JavaScript Comparison Table — https://dorey.github.io/JavaScript-Equality-Table/
wtfjs — небольшой блог о языке, который мы все так любим, не смотря на то что он дает много поводов его ненавидеть — https://wtfjs.com/
Как преобразовать строку в число в JavaScript
Узнайте, как преобразовать строку в число с помощью JavaScript
JavaScript предоставляет различные способы преобразования строкового значения в число.
Лучше всего: использовать объект Number
На мой взгляд, лучше всего использовать объект Number в контексте, не являющемся конструктором (без ключевого слова new
):const count = Number('1234') / /1234
Это касается и десятичных знаков.
Число — это объект-оболочка , который может выполнять множество операций. Если мы используем конструктор ( new Number("1234")
), он возвращает нам объект Number вместо числового значения, так что будьте внимательны.
Следите за разделителями между цифрами:
Число('10,000') //NaN Число('10.00') //10 Number('10000') //10000
В случае, если вам нужно проанализировать строку с десятичными разделителями, используйте вместо этого Intl.NumberFormat
.
Другие решения
Использовать
parseInt()
и parseFloat()
Другим хорошим решением для целых чисел является вызов функции parseInt()
const count = parseInt('1234', // 1234
Не забывайте о втором параметре, который является основанием, всегда равным 10 для десятичных чисел, иначе преобразование может попытаться угадать основание и дать неожиданные результаты.
parseInt()
пытается получить число из строки, которая содержит не только число:
parseInt('10 львов', 10) //10
но если строка не начинается с цифры, вы получите NaN
(не число):
parseInt("Мне 10" , 10) //NaN
Также, как и в случае с Number, он ненадежен с разделителями между цифрами:
parseInt('10,000', 10) //10 ❌ parseInt('10. 00', 10) //10 ✅ (считается десятичным числом, вырезано) parseInt('10.000', 10) //10 ✅ (считается десятичной дробью, вырезано) parseInt('10.20', 10) //10 ✅ (считается десятичной дробью, вырезано) parseInt('10.81', 10) //10 ✅ (считается десятичным числом, вырезано) parseInt('10000', 10) //10000 ✅
Если вы хотите сохранить десятичную часть, а не просто получить целую часть, используйте parseFloat()
. Обратите внимание, что в отличие от
его брат parseInt()
, он принимает только один аргумент — строку для преобразования:
parseFloat('10,000') //10 ❌ parseFloat('10.00') //10 ✅ (считается десятичным числом, вырезано) parseFloat('10.000') //10 ✅ (считается десятичным числом, вырезано) parseFloat('10.20') //10.2 ✅ (считается десятичным числом) parseFloat('10.81') //10.81 ✅ (считается десятичным числом) parseFloat('10000') //10000 ✅
Используйте
+
Один «трюк» заключается в использовании унарного оператора +
перед строкой:
+'10,000'//NaN ✅ +'10. 000'//10 ✅ +'10.00' //10 ✅ +'10.20' //10.2 ✅ +'10,81'//10,81 ✅ +'10000' //10000 ✅
Посмотрите, как он возвращает
в первом примере, что является правильным поведением: это не число.
Использование
Math.floor()
Аналогичен унарному оператору +
, но возвращает целую часть, заключается в использовании Math.floor()
:
Math.floor('10,000') //NaN ✅ Math.floor('10.000') //10 ✅ Math.floor('10.00') //10 ✅ Math.floor('10.20') //10 ✅ Math.floor('10.81') //10 ✅ Math.floor('10000') //10000 ✅
Используйте
* 1
Как правило, это один из самых быстрых вариантов, ведет себя как унарный оператор +
, поэтому он не выполняет преобразование в целое число, если число поплавок.
'10 000' * 1 //NaN ✅ '10.000' * 1//10 ✅ '10.00' * 1 //10 ✅ '10.20' * 1 //10.2 ✅ '10,81' * 1 //10,81 ✅ '10000' * 1 //10000 ✅
Производительность
Каждый из этих методов имеет разную производительность в разных средах, поскольку все зависит от реализации. В моем случае * 1
является победителем по производительности в 10 раз быстрее, чем другие альтернативы.
Используйте JSPerf, чтобы попробовать себя:
2 способа преобразования значений в логические значения в JavaScript
Мне больше всего нравится использовать !!
. Это также рекомендуемый метод в руководстве по стилю JavaScript от Airbnb 👍
Преобразовать значения в логические
Строка
Число
Ложные значения
В JavaScript существует 6 ложных значений. Если вы преобразуете любой из них в логическое значение
, оно вернет false
.
Все, что не входит в ложный список, вернет true
👍
Дополнительную информацию об этом вы можете прочитать в моих примечаниях к коду о ложных значениях
Примеры
Применение !!
о ложных значениях
Применение Boolean
на ложных значениях
Как
!!
работ Первый !
приводит значение к логическому и инвертирует его. В этом случае !value
вернет false
. Таким образом, чтобы обратить его обратно к , истинному
, мы вставляем еще !
на нем. Отсюда и двойное использование !!
.
Остерегайтесь
"false"
Обратите внимание, что "false"
находится в кавычках '
. Хотя написано false
, на самом деле это строка. Я знаю, что большинство из вас не купятся на это, но если вы похожи на меня, вы можете просто быть начеку, чтобы не пропустить эти забавные трюки с разумом, которые люди могут разыграть с вами 😂
@tassoevan: Мне нравится фильтровать ложь значения из таких массивов: myArray.filter(Boolean)
@fleonus: Мне нравится !+!
просто чтобы быть крутым и сбить людей с толку0002 логическое значение против !!
Похоже на !!
немного быстрее, чем Boolean
Какой из них использовать?
Я получил много комментариев к этому сообщению. Некоторые люди предпочитают логическое значение
, потому что оно более явное.
Но Кайл Симпсон из You Don’t Know JS упомянул, что оба являются явными.
Кайл Симпсон: YDKJS — Принуждение
Не думаю, что у меня есть для вас отличный ответ. Вы будете знать свою команду намного лучше, чем я. Я буду продолжать использовать !!
в моих личных проектах, потому что это меньше печатать, и я понимаю этот синтаксис. Но если бы я был в команде, я бы выбрал Boolean
, потому что я думаю, что большинство разработчиков поняли бы это лучше. Независимо от того, какой из них вы выберете, самое главное, чтобы соответствовал . Не переключайтесь между ними в кодовой базе. Выберите один и придерживайтесь его 💪
Вдогонку к замечательному комментарию, который я получил:
@patrick_developer: Я говорю, что нужно понимать оба на тот случай, если вам будут представлены разные кодовые базы, которые используют каждый из них. Знание — сила.
Другими словами, одно не лучше другого. Я бы сказал, что это больше предпочтения. Так что вы не ошибетесь. Но не лишайте себя понимания обоих. Как сказал Патрик, «Знание — сила» 💪
Избегайте
new Boolean
Используйте примитивы вместо типов объектов булева. Примитивы дешевле, и их следует предпочесть объектному типу.
CJ J. : new Boolean(str)
возвращает тип объекта. Boolean(str)
просто возвращает примитивное логическое значение. Я подозреваю, что Boolean(str)
быстрее, чем !!str
, потому что это только одна операция, но также вполне возможно, что браузеры реализуют такую оптимизацию, что когда они видят !!
они знают, что нужно напрямую привести аргумент к логическому примитиву (вместо фактического выполнения NOT()
дважды подряд).
CJ J. : Примитивы дешевы, потому что они неизменяемы, поэтому вы можете делиться ссылками и не хранить какое-либо состояние экземпляра.