Что такое приведение типов в Javascript?

122

Что такое приведение типов в Javascript?

Например, об использовании ==вместо ===?

gespinha
источник
21
(true == 1) => true/ (true === 1) => false.
VisioN
5
@VisioN ваш комментарий совсем не помогает, я спрашиваю: «почему» это происходит?
gespinha
3
Это происходит потому, что таким образом был разработан JavaScript. Мой комментарий должен ответить на ваш главный вопрос: что такое приведение типов в Javascript?
VisioN
6
Через YDJS: «Преобразование значения из одного типа в другой часто называется« приведением типа », когда оно выполняется явно, и« принуждением », когда выполняется неявно (принудительно в соответствии с правилами использования значения)». - github.com/getify/You-Dont-Know-JS/blob/master/…
mattLummus

Ответы:

177

Приведение типов означает, что когда операнды оператора относятся к разным типам, один из них будет преобразован в «эквивалентное» значение типа другого операнда. Например, если вы это сделаете:

boolean == integer

логический операнд будет преобразован в целое число: falseстановится 0, trueстановится 1. Затем два значения сравниваются.

Однако при использовании оператора сравнения ===без преобразования такое преобразование не происходит. Когда операнды имеют разные типы, этот оператор возвращает falseи сравнивает значения, только если они одного типа.

Barmar
источник
1
Как я могу применить это на практике? Разве мне не следует всегда использовать, ===когда я хочу сравнить, равно ли одно значение другому?
gespinha
1
Это зависит от того, что вы делаете. См. Связанный вопрос.
Barmar
8
@GEspinha ну, это "искусство" использования слабо типизированного языка. Некоторые люди так думают, и в целом думают, что слабо типизированные языки - это бич мира программирования. Однако, если вы знаете, что делаете, это может сделать код более коротким и гибким.
Crayon Violent
2
@Barmar Это также относится к > , <?
Рой Намир
2
Отличный справочник и объяснение по принуждению: github.com/getify/You-Dont-Know-JS/blob/master/…
Грег Белл
57

Давайте начнем с краткого введения в системы типов, которые, я думаю, помогут вам понять общую идею приведения типов.

Система типов языка определяет правила, которые говорят нам, какие типы данных существуют на этом языке и как их можно комбинировать с помощью различных операторов. Например, одно такое правило может указывать, что оператор плюс (+) действует только с числами. Эти правила существуют в первую очередь для того, чтобы вы не прострелили себе ногу. Но что происходит, когда программист нарушает это правило в программе? Ничто не мешает программисту печатать {} + {}или вводить “hello” + 5программу, даже если язык не считает, что эти выражения имеют какой-либо смысл.

Что в конечном итоге происходит в этих ситуациях, зависит от того, насколько язык строг в отношении правил типов.

Система типов языков часто придерживается одной из двух позиций о том, что вы нарушаете ее правила:

  1. Скажите: «Эй, это не круто!» и сразу же вылетит ваша программа.
  2. Скажите: «Я ничего не могу сделать с {}… но я могу что-то сделать с числами» и попытайтесь преобразовать {} в число.

Языки с системами типов, которые занимают первое место в отношении правил, в просторечии называются «строго типизированными» языками. Они строги и не позволяют вам нарушать его правила. Те, которые используют второй подход (например, JavaScript), называются «слабо типизированными» или «слабо типизированными» языками. Конечно, вы можете нарушить правила, но не удивляйтесь, когда он принудительно преобразует тип данных, который вы описали в своей программе, в соответствии с его правилами. Такое поведение известно как… (барабанная дробь)… типа принуждения .

Теперь давайте посмотрим на несколько примеров на JavaScript. Во-первых, давайте начнем с выражения, которое не приводит к приведению типов.

5 + 5

Использование оператора + с двумя числами, что совершенно верно. Программа будет рассматривать + как «сложить» и успешно сложить два числа. Преобразование не требуется.

Но что насчет …

[] + 5

Ой ой. В JavaScript это +может означать сложение двух чисел или соединение двух строк. В этом случае у нас нет ни двух чисел, ни двух строк. У нас есть только одно число и объект. Согласно правилам типов в JavaScript, это не имеет логического смысла. Поскольку он прощает, что вы нарушаете его правила, вместо того, чтобы разбиться, он все равно пытается разобраться в этом. Так что же делает JavaScript? Что ж, он знает, как объединять строки, поэтому он преобразует как [], так и 5 в строки, и результатом является строковое значение «5».

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

==не застрахован от поведения преобразования типов в JavaScript. Выражения, такие как, 5 == “5”будут иметь значение true, потому что JavaScript попытается преобразовать одно из них, чтобы оно сравнивало данные того же типа.

Во многих случаях это нежелательно, потому что вы, вероятно, хотите знать, относятся ли некоторые данные, с которыми вы сравниваете, к другому типу, чтобы вы могли решить, что с ними делать. Здесь на ===помощь приходит оператор. Когда вы его используете ===, преобразование типа не происходит. Следовательно, выражение 5 === “5”будет иметь значение false.

linstantnoodles
источник
4
спасибо за хорошее объяснение, особенно за «Система типов языков часто занимает одну из двух позиций»
Хумоюн Ахмад
1
Это должен быть принятый ответ, поскольку он показывает автоматическое приведение типов в нескольких аспектах, а не только в примере сравнения ==. Этот ответ в целом намного лучше отвечает на вопрос и устраняет всякую двусмысленность. Спасибо, что нашли время написать это.
the chad
6

В Python, если вы попытаетесь добавить, скажем, строки и целые числа, вы получите ошибку:

>>> "hi" + 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Но в JavaScript этого нет. 10Преобразуется в строку:

> "hi" + 10
"hi10"

«Типовое принуждение» - это всего лишь причудливый неправильный термин для вышесказанного. На самом деле ни один язык не имеет «типов» в смысле Java или C или других языков со статическими системами типов. То, как языки обрабатывают взаимодействия между различными нестатически типизированными значениями, является вопросом выбора и соглашения.

Клаудиу
источник
1
Я думаю, что в приведенном вами примере есть небольшая проблема. То, что вы предложили в качестве примера для JS, безупречно работает с Java и C #. Итак, согласно этому ответу, если кто- то придет к выводу, что Java и C # поддерживают приведение типов , это не будет полностью правдой ...
Ромео Сьерра
3

позвольте мне объяснить приведение типов на следующем примере

Принуждение типа означает, что Javascript автоматически (на лету) преобразует переменную из одного типа данных в другой.

Пример: 123 + "4"обычно вызывает ошибку, но в Javascript из-за приведения типов 1234возникает строка

if(23 == "23"){
    console.log(" this line is inside the loop and is executed ");
}

В приведенном выше коде из-за приведения типов - JavaScript считает 23(число) и "23"(строка) одним и тем же. это делает условие истинным и печатает console.log

В другом случае

if(23 === "23"){
   console.log(" this line is inside the loop and is NOT executed");
}

В ===случае, если Javascript не выполняет приведение типов, и поскольку 23это число, а "23"это String, и из-за того, что ===эти два типа данных различны, что приводит к ложному условию. Он не печатает console.log

Простыми словами

В данном случае =это оператор присваивания, который присваивает такие значения, как var a = 3;и т. Д.

(ниже операторы для сравнения)

В этом случае ==Javascript преобразует / приводит один тип данных к другому, а затем сравнивает его.

В этом случае === Javascript не конвертирует / не принуждает тип данных

Во избежание ошибок и в целях отладки ===в основном используется

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

PRagh
источник
2

Что такое принуждение:

Приведение типов в javascript происходит, когда движок Javascript должен выполнить определенную операцию, для которой ему нужны данные определенного типа. Когда механизм встречает данные определенного типа, которые не подходят для операции, он затем переводит данные в определенный тип. Это необходимо, потому что переменные в javascript динамически типизируются, что означает, что данной переменной можно присвоить значение любого типа.

Пример:


if(1){
  // 1 gets coerced to true
}


if(4 > '3') {
  // 3 gets coerced into a number
}


44 == "44"  // true, the string 44 gets converted to a nr

Логическое принуждение:

При принуждении javascript все значения преобразуются в, trueза исключением следующих значений, к которым принудительно приводятся false:

console.log(!!"");         // false
console.log(!!0);          // false
console.log(!!null);       // false
console.log(!!undefined);  // false
console.log(!!NaN);        // false
console.log(!!false);      // false

Также обратите внимание, что в приведенном выше примере двойная! используется оператор. ! Оператор mark переводит значение в логическое значение с противоположным значением. Мы можем использовать этот оператор дважды, чтобы преобразовать любое значение в логическое.

Виллем ван дер Вин
источник
1

a == bозначает, что javascript будет оценивать aна bоснове того, могут ли значения быть оценены одинаково. Например, false == 0будет оцениваться значение true, потому что 0 также является значением логического false. Однако false === 0будет оцениваться false, потому что строго сравнивая, 0 не то же самое физическое значение, что false. Другой пример: в false == ''основном свободное сравнение против строгого, потому что javascript - это слабо типизированный язык. То есть javascript будет пытаться преобразовать переменную в зависимости от контекста кода, и это приведет к уравниванию значений, если они не будут строго сравниваться. php также имеет такое поведение.

Crayon Violent
источник
0 is not the same physical value as false, ИМО физически falseточно 0в памяти. Я бы сказал, что они разные по типу, так falseкак логическое значение, а 0целое число.
VisioN
1

Приведение типов - это процесс преобразования значения из одного типа в другой (например, строки в число, объект в логическое и т. Д.). Любой тип, будь то примитив или объект, является допустимым объектом для приведения типов. Напомним, примитивы: число, строка, логическое значение, null, undefined + символ (добавлено в ES6).

Неявное и явное принуждение. Принуждение типа может быть явным и неявным.

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

Поскольку JavaScript является языком со слабой типизацией, значения также могут автоматически преобразовываться между разными типами, и это называется неявным приведением типов. Обычно это происходит , когда вы применяете операторы значений различных типов, как 1 == null, 2/’5', null + new Date()или он может быть вызван окружающим контекстом, как и с if (value) {…}, где значением приводятся к булева.

Один оператор, который не запускает неявное приведение типа ===, называется оператором строгого равенства. С ==другой стороны, оператор свободного равенства выполняет как сравнение, так и приведение типов, если это необходимо.

Неявное приведение типов - это обоюдоострый меч: это отличный источник разочарований и дефектов, но также и полезный механизм, позволяющий писать меньше кода без потери читабельности.

Три типа преобразования . Первое правило, которое необходимо знать, - в JavaScript есть только три типа преобразования:

  • нанизывать
  • булево
  • чтобы пронумеровать

Во-вторых, логика преобразования примитивов и объектов работает по-разному, но и примитивы, и объекты могут быть преобразованы только этими тремя способами.

Начнем сначала с примитивов.

Преобразование строки

Чтобы явно преобразовать значения в строку, примените функцию 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()функцию. Неявное преобразование происходит в логическом контексте или запускается логическими операторами ( || && !).

Boolean(2)          // explicit
if (2) { ... }      // implicit due to logical context
!!2                 // implicit due to logical operator
2 || 'hello'        // implicit due to logical operator

Примечание. Логические операторы, такие как || and &&внутренние логические преобразования, фактически возвращают значение исходных операндов, даже если они не являются логическими.

// 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

Поскольку есть только 2 возможных результата логического преобразования: истина или ложь, проще запомнить список ложных значений.

Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false

Любое значение , которое не входит в список преобразуется в trueтом числе object, function, Array, Date, определяемого пользователем типа, и так далее. Символы - истинные ценности. Пустой объект и массивы также являются истинными значениями:

Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true

Числовое преобразование

Для явного преобразования просто примените Number()функцию, как и с Boolean()и String().

Неявное преобразование сложно, потому что оно запускается в большем количестве случаев:

  • операторы сравнения (>, <, <=,> =)

  • побитовые операторы (| & ^ ~)

  • арифметические операторы (- + * /%). Обратите внимание, что двоичный + не запускает числовое преобразование, если любой операнд является строкой.

  • унарный + оператор

  • оператор свободного равенства == (включая! =).

    Обратите внимание, что == не запускает числовое преобразование, если оба операнда являются строками.

    Number ('123') // явный + '123' // неявный 123! = '456' // неявный 4> '5' // неявный 5 / null // неявный true | 0 // неявный

Вот как примитивные значения преобразуются в числа:

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
Теджас Савалия
источник
medium.com/@tejassavaliya/…
Теджас Савалия
0
var str = 'dude';
console.log(typeof str); // "string"
console.log(!str); // false
console.log(typeof !str); // "boolean"

Пример переменной, которая изначально объявлена ​​как строка, преобразованная в логическое значение с помощью! оператор

Мистер П
источник
3
Пожалуйста, уточните свой ответ. Ответы только на код не очень полезны.
cezar
3
лично я считаю, что только примеры кода лаконичны,
Мистер П.
0

Приведение типов - это процесс преобразования значения из одного типа в другой (например, строки в число, объект в логическое и т. Д.). Любой тип, будь то примитив или объект, является допустимым объектом для приведения типов. Напомним, примитивы: число, строка, логическое значение, null, undefined + символ (добавлено в ES6).

Приведение типов может быть явным и неявным.

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

Поскольку JavaScript является языком со слабой типизацией, значения также могут автоматически преобразовываться между разными типами, и это называется неявным приведением типов. Обычно это происходит, когда вы применяете операторы к значениям разных типов, например 1 == null, 2 / '5', null + new Date (), или это может быть вызвано окружающим контекстом, например, с if (value) {… }, где значение приводится к логическому.

вот пример неявного приведения типа:

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

подробнее: https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/

Махди Салехян
источник
-2

Если типы данных не равны друг другу, то происходит принуждение. например 3 == "3" или логическое == целое число

ASAbir
источник