Напоминание впереди: длина статьи длинная, пожалуйста, поставьте лайк или добавьте ее в закладки, вы легко найдете ее, когда будете читать ее в следующий раз.
Когда дело доходит до неявного преобразования js, первая реакция многих людей: pit.
Действительно, для непосвященныхjs隐式转换
Есть много непредсказуемых мест, и я считаю, что многие люди глубоко затронуты, поэтому в процессе разработки вы можете использовать===
чтобы попытаться избежать неявных преобразований. Однако для более глубокого пониманияjavascript
, в духе тяги к знаниям, давайте разбирать и анализировать на большом количестве примеровjs隐式转换
,знакомыйjs隐式转换
правила, сделайте это "явным" в ваших глазах.
Начните с вопроса интервью
Давайте посмотрим на классический вопрос интервью
определить переменную
a
, так что следующее выражение приводит кtrue
a == 1 && a == 2 && a == 3
И такая операция? Давайте сначала попробуем определитьa = true
?
var a = true
a == 1 && a == 2 && a == 3 // false
Однако это не оправдало ожиданий, словно задев слепое пятно знаний. . . Неважно, давайте сначала положим его, давайте заглянем еще в несколько ям
[] == ![] // true
[] == 0 // true
[2] == 2 // true
['0'] == false // true
'0' == false // true
[] == false // true
[null] == 0 // true
null == 0 // false
[null] == false // true
null == false // false
[undefined] == false // true
undefined == false // false
Смущенный? Это не имеет значения! Далее я принесу вам полное пониманиеjavascript的隐式转换
.
правила неявного преобразования javascript
1. ToString, ToNumber, ToBoolean, ToPrimitive
Нам нужно понять основные правила преобразования между типами данных js, такие как взаимное преобразование между числами, строками, логическими значениями, массивами и объектами.
1.1 ToString
что здесь сказано
ToString
не возражаюtoString方法
, но относится к операции преобразования значения другого типа в строковый тип.
Здесь мы обсуждаемnull
,undefined
,布尔型
,数字
,数组
,普通对象
Правила преобразования в строки.
- ноль: преобразовать в
"null"
- undefined: преобразовать в
"undefined"
- Логический тип:
true
а такжеfalse
были преобразованы в"true"
а также"false"
- Тип числа: преобразование в строковую форму числа, например
10
Перевести в"10"
,1e21
Перевести в"1e+21"
- Массив: Преобразование в строку заключается в соединении всех элементов в соответствии с «,», что эквивалентно вызову массива
Array.prototype.join()
такие методы, как[1, 2, 3]
Перевести в"1,2,3"
, пустой массив[]
Преобразовать в пустую строку в массивеnull
илиundefined
, будет рассматриваться как пустая строка - Обычный объект: преобразование в строку эквивалентно его непосредственному использованию.
Object.prototype.toString()
,вернуть"[object Object]"
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(10) // '10'
String(1e21) // '1e+21'
String([1,2,3]) // '1,2,3'
String([]) // ''
String([null]) // ''
String([1, undefined, 3]) // '1,,3'
String({}) // '[object Objecr]'
объектtoString
способ удовлетворитьToString
правила эксплуатации.
Примечание. Упомянутые выше правила действуют по умолчанию, если вы измените настройки по умолчанию.
toString()
методы, которые приводят к разным результатам
1.2 ToNumber
ToNumber
Относится к операции преобразования других типов в числовые типы.
- ноль: преобразовать в
0
- undefined: преобразовать в
NaN
- Строка: если это чистое число, оно будет преобразовано в соответствующее число, а пустые символы будут преобразованы в
0
, в противном случае это будет считаться ошибкой преобразования и преобразовано вNaN
- Логический:
true
а такжеfalse
быть преобразован в1
а также0
- Массивы. Массивы сначала преобразуются в примитивные типы, т.
ToPrimitive
, а затем обработаны в соответствии с указанными выше правилами в соответствии с преобразованным исходным типом, примерноToPrimitive
, который будет описан ниже - Объект: обработка того же массива
Number(null) // 0
Number(undefined) // NaN
Number('10') // 10
Number('10a') // NaN
Number('') // 0
Number(true) // 1
Number(false) // 0
Number([]) // 0
Number(['1']) // 1
Number({}) // NaN
1.3 ToBoolean
ToBoolean
Относится к операциям, которые преобразуют другие типы в логические типы.
ложное значение только в jsfalse
,null
,undefined
,空字符
,0
а такжеNaN
, другие значения преобразуются в логические значения какtrue
.
Boolean(null) // false
Boolean(undefined) // false
Boolean('') // flase
Boolean(NaN) // flase
Boolean(0) // flase
Boolean([]) // true
Boolean({}) // true
Boolean(Infinity) // true
1.4 ToPrimitive
ToPrimitive
Относится к операции преобразования типов объектных типов (таких как объекты, массивы) в примитивные типы.
- Когда тип объекта необходимо преобразовать в примитивный тип, он сначала ищет тип объекта.
valueOf
метод, еслиvalueOf
метод возвращает значение примитивного типа, тогдаToPrimitive
Результат - это значение - если
valueOf
не существует илиvalueOf
Если метод возвращает значение, не являющееся примитивным типом, он попытается вызвать функцию объекта.toString
метод, то есть будет следовать за объектомToString
правила, затем используйтеtoString
возвращаемое значение какToPrimitive
результат.
Примечание. Для различных типов объектов
ToPrimitive
Правила разные, напримерDate对象
Мы сначала позвонитьtoString
, вы можете обратиться кстандарт ECMA
еслиvalueOf
а такжеtoString
Если ни один из них не возвращает значение исходного типа, будет выдано исключение.
Number([]) // 0
Number(['10']) //10
const obj1 = {
valueOf () {
return 100
},
toString () {
return 101
}
}
Number(obj1) // 100
const obj2 = {
toString () {
return 102
}
}
Number(obj2) // 102
const obj3 = {
toString () {
return {}
}
}
Number(obj3) // TypeError
Как упоминалось ранее, тип объектаToNumber
придет первымToPrimitive
, а затем в соответствии с преобразованным оригинальным типомToNumber
-
Number([])
, сначала будет вызван пустой массивvalueOf
, но сам возвращаемый массив не является примитивным типом, поэтому он продолжит вызыватьtoString
,получать空字符串
, эквивалентноNumber('')
, поэтому преобразованный результат"0"
- По аналогии,
Number(['10'])
эквивалентноNumber('10')
, получил ответ10
-
obj1
изvalueOf
метод возвращает примитивный тип100
,такToPrimitive
Результат100
-
obj2
нетvalueOf
, но существуетtoString
и возвращает примитивный тип, такNumber(obj2)
Результат102
-
obj3
изtoString
Возвращаемый метод не является примитивным типом и не можетToPrimitive
, поэтому выдает ошибку
Увидев это, вы думаете, что освоили его полностью? Не забывайте, что этот вопрос интервью и эта куча запутанных суждений еще не решены.В духе жажды знаний, продолжайте читать.
2. Неявные правила преобразования для нестрогих сравнений на равенство (==)
宽松相等(==)
а также严格相等(===)
Разница в том, что при сравнении будет выполнено нечеткое равенство隐式转换
. Теперь рассмотрим правила конвертации в разных случаях.
2.1 Сравнение равенства между логическими типами и другими типами
- если только
布尔类型
Для участия в сравнении布尔类型
Значение сначала преобразуется в数字类型
- согласно с
布尔类型
изToNumber
правило,true
Перевести в1
,false
Перевести в0
false == 0 // true
true == 1 // true
true == 2 // false
Кому-то может показаться, что цифры
2
является истинностным значением, поэтомуtrue == 2
Это должно быть правдой, теперь понять, булевой типtrue
Участие в сравнениях на равенство сначала преобразуется в числа.1
, эквивалентно1 == 2
, результат конечноfalse
мы обычно используемif
При судействе обычно пишут так
const x = 10
if (x) {
console.log(x)
}
здесьif(x)
изx
будет преобразован в логический тип здесь, поэтому код может выполняться нормально. Но если написать так:
const x = 10
if (x == true) {
console.log(x)
}
Код не будет выполняться должным образом, потому чтоx == true
эквивалентно10 == 1
2.2 Сравнение равенства между числовыми и строковыми типами
- когда
数字类型
а также字符串类型
При сравнении равенства字符串类型
будет преобразован в数字类型
- судя по строке
ToNumber
Правила, если это строка в виде чистого числа, она преобразуется в соответствующее число, а нулевой символ преобразуется в0
, в противном случае это будет считаться ошибкой преобразования и преобразовано вNaN
0 == '' // true
1 == '1' // true
1e21 == '1e21' // true
Infinity == 'Infinity' // true
true == '1' // true
false == '0' // true
false == '' // true
Являются ли результаты сравнения выше, чем вы ожидали? По правилам строки преобразуются в числа, а логические значения преобразуются в числа, так что результат очевиден.
не обсуждается здесь
NaN
, потому чтоNaN
и не равен никакому значению, в том числе самому себе.
2.3 Сравнение равенства между объектными типами и примитивными типами
- когда
对象类型
а также原始类型
При сравнении равенства对象类型
последуетToPrimitive
Правила преобразуются в原始类型
'[object Object]' == {} // true
'1,2,3' == [1, 2, 3] // true
Посмотрите на пример, приведенный в начале статьи
[2] == 2 // true
множество[2]
является типом объекта, поэтомуToPrimitive
операция, то есть вызов сначалаvalueOf
позвони сноваtoString
, по массивуToString
правила работы, получат результаты"2"
,
в то время как строка"2"
2
При сравнении он будет сначала преобразован в числовой тип, поэтому окончательный результатtrue
.
[null] == 0 // true
[undefined] == 0 // true
[] == 0 // true
По указанному выше массивуToString
Правила работы, элементы массиваnull
илиundefined
, элемент рассматривается как空字符串
обработка, а пустой массив[]
также преобразован в空字符串
, поэтому приведенный выше код эквивалентен
'' == 0 // true
'' == 0 // true
'' == 0 // true
空字符串
будут преобразованы в числа0
, так что результатtrue
.
попробуйте метод valueOf
const a = {
valueOf () {
return 10
}
toString () {
return 20
}
}
a == 10 // true
объект
ToPrimitive
Сначала будет вызвана операцияvalueOf
метод иa
изvalueOf
метод возвращает значение примитивного типа, поэтомуToPrimitive
Результат операции естьvalueOf
возвращаемое значение метода10
.
Кстати говоря, вы думали о первых вопросах интервью?
объект каждый раз и примитивный тип делать==
При сравнении будет сделано один разToPrimitive
операцию, то можем ли мы определить содержащуюvalueOf
объект метода, а затем реализовать его, накопив определенное значение?
попробуй
const a = {
// 定义一个属性来做累加
i: 1,
valueOf () {
return this.i++
}
}
a == 1 && a == 2 && a == 3 // true
Результат правильный, как и следовало ожидать. Конечно, когда нет определенияvalueOf
метод, использованиеtoString
метод тоже возможен.
const a = {
// 定义一个属性来做累加
i: 1,
toString () {
return this.i++
}
}
a == 1 && a == 2 && a == 3 // true
2.4 Сравнение нулевого, неопределенного и других типов
-
null
а такжеundefined
Результат свободного равенства верен, как мы все знаем
Второй,null
а такжеundefined
являются ложными значениями, то
null == false // false
undefined == false // false
Это отличается от того, что я думал? Зачем? первый,false
Перевести в0
,а потом? нет тогда,ECMAScript规范
оговорено вnull
а такжеundefined
друг друга宽松相等(==)
, а также равно самому себе, но не всем другим значениям宽松相等(==)
.
наконец
Теперь смотрим на предыдущий кусок кода и становится понятно, что многое
[] == ![] // true
[] == 0 // true
[2] == 2 // true
['0'] == false // true
'0' == false // true
[] == false // true
[null] == 0 // true
null == 0 // false
[null] == false // true
null == false // false
[undefined] == false // true
undefined == false // false
Наконец, я хочу сказать всем, не отвергайте слепо неявное преобразование javascript, вы должны научиться его использовать.В вашем коде может быть много неявных преобразований, но вы их игнорируете.Причина, это может помочь нам глубоко понимать javascript.
(Прошло много времени с тех пор, как я прочитал это, это была тяжелая работа, но я пишу уже давно, пожалуйста, ставьте палец вверх и уходите)