В JS много типов данных, а идентификация и взаимное преобразование разных типов данных также является распространенным тестом на собеседованиях.В этой статье в основном говорится о преобразовании типов и обнаружении типов.
тип данных
Типы данных в JS в основном делятся на две категории: примитивные типы (типы значений) и ссылочные типы. Общие типы данных показаны на следующем рисунке:
Примитивные типы данных хранятся в стеке, а ссылочные типы хранятся в стеке как ссылочный адрес, который указывает на объект данных в куче. должен быть в курсеnullЗдесь мы считаем в примитивных типах, но вы используетеtypeofкогда ты узнаешь, что онobject, причина в том, что даже если он объект, он должен хранить в стеке адрес ссылки, но он пустой объект, поэтому этот адрес пустой, то есть он не соответствует никаким данным в куче, он не имеет данных в куче, существует только в стеке, поэтому здесь он считается примитивным типом. Ссылочный тип на самом деле в основномObject,Arrayа такжеFunctionЭто на самом делеObjectполученный.Более подробные сведения об этих двух типах памяти см. в этой статье.
Давайте посмотрим на разницу между этими двумя типами:
примитивный тип
-
Значение примитивного типа нельзя изменить, только переназначив. Попытка изменить его, как показано ниже, не сработает, но все переназначение сработает.
-
Сравнение примитивных типов заключается в сравнении значений, если значения равны, они равны
тип ссылки
-
Типы ссылочных значений могут быть изменены, хотя на этот раз мы уделяем внимание изменению
aсвойства внутри, ноaАдрес ссылки в стеке не изменился, но изменились данные в куче. -
При сравнении ссылочных типов сравниваются их индексные адреса, а не их значения. Например, следующие два объекта выглядят одинаково, но их ссылочные адреса не совпадают, но они не равны:
Чтобы сделать их равными, вы должны напрямую преобразовать
bназначить какa, чтобы их ссылочные адреса были одинаковыми и равными.
преобразование типов
В JS преобразование типов выполняется при вычислении разных типов данных, как в следующем примере:
В приведенном выше примере мы использовали сложение и вычитание для работы с несколькими нечисловыми типами.В это время JS выполнит неявное преобразование типов, а затем выполнит операции сложения и вычитания. Помимо неявного преобразования самого JS, иногда мы будем активно выполнять преобразование типов, которое является даже явным преобразованием типов.
неявное преобразование типов
преобразовать в строку
часто появляются в+операция, и один из операндов не является числовым типом
let s = 4 + 'px' + 5;
console.log(s); // 4px5
s = 123e-2 + 'a';
console.log(s); // 1.23a
Преобразовать в числовой
Часто появляется в математических операциях, указывающих на объединение строк.+За исключением операций
let s = 'abc';
console.log(+s, -s); // NaN, NaN
s = ' 123 ';
console.log(+s, -s); // 123 -123
s = new Date();
console.log(+s, -s); // 1588675647421 -1588675647421 (这个操作相当于取毫秒数)
Преобразование в логическую сцену
Часто появляется в if или логических операциях
let s = 'abc';
if(s) {
console.log(s); // abc
}
console.log(!!s); // true
Следующие значения преобразуются в логическое преобразование вfalse, кроме этогоtrue:
- 0
- NaN
- '' (пустой строки)
- null
- undefined
== оператор
когда мы используем==При сравнении, если типы с обеих сторон разные, JS выполнит преобразование типов, а затем сравнит,===преобразование типов не будет выполнено, если===Типы данных с обеих сторон разные, возврат напрямуюfalse.
Выше приведены лишь некоторые из случаев.Чтобы узнать больше, вы можете обратиться к следующей таблице, взятой из MDN. В этой таблице много содержимого, часть из которого прямо определяется спецификацией, напримерnull == undefined, а о логике и речи быть не может. Мы можем проверить эту таблицу, если не уверены, но ее не рекомендуется использовать в реальной разработке.==Да, потому что если вы неправильно запомните это отношение преобразования, это может привести к ошибкам, которые сложнее устранить. Обычно рекомендуется использовать его напрямую.===.
Правила преобразования
В следующих таблицах приведены некоторые правила преобразования из JS Definitive Guide:
явное преобразование типов
Явное преобразование типов — это тип, который мы пишем в коде для явного преобразования, что может сделать код более понятным и является рекомендуемой практикой при реальной разработке.
преобразовать строку
Можно использовать явное преобразование в строкуtoStringметод, результат его выполнения обычно такой же, как иString()метод тот же. типа КоличествоtoStringМетод также поддерживает параметры, которые могут указывать базу для преобразования. На следующих диаграммах показаны некоторые примитивные типыtoString(),nullа такжеundefinedнетtoStringметод вызов сообщит об ошибке:
типа КоличествоtoStringМетод поддерживает шестнадцатеричный формат:
Значение революции
Преобразование в числовое значение очень простое, и часто используются эти два глобальных метода:parseIntа такжеparseFloat.
объект для строки
Преобразование объектов в строки и числа немного сложнее, поэтому давайте рассмотрим их отдельно. Существует три основных способа преобразования объектов в строки:
-
value.toString()Это было сказано раньше
-
'' + value. Это неявное преобразование, упомянутое ранее, ноvalueЕсли это объект, он будет преобразован в следующем порядке:- сначала позвони
value.valueOfметод, который возвращает значение, если значение является примитивом - В противном случае позвоните
value.toStringметод, который возвращает значение, если значение является примитивом - В противном случае сообщается об ошибке TypeError
- сначала позвони
-
String(value). Это явное преобразование, упомянутое ранее Процесс аналогичен предыдущему, но вызовtoStringа такжеvalueOfпорядок разный.- сначала позвони
value.toStringметод, который возвращает значение, если значение является примитивом - В противном случае позвоните
value.valueOfметод, который возвращает значение, если значение является примитивом - В противном случае сообщается об ошибке TypeError
- сначала позвони
должны знать о том,DateОбъект немного особенный, он всегда звонитtoStringметод.
Давайте напишем кусок кода для проверки:
Object.prototype.valueOf = function() {
return 'aaa';
}
Object.prototype.toString = function() {
return 'bbb';
}
let a = {};
let b = '' + a;
let c = String(a);
console.log(b);
console.log(c);
Вывод приведенного выше кода, как мы и ожидали:
значение поворота объекта
Существует два основных способа преобразования типа объекта в значение:
+valueNumber(value)
Логика выполнения для обоих одинакова:
- сначала позвони
valueOfметод, который возвращает значение, если значение является примитивом - В противном случае позвоните
toStringметод, тоtoStringПреобразование возвращаемого значения в числовое значение
Как обычно, напишите пример, чтобы увидеть:
Object.prototype.valueOf = function() {
return {};
}
Object.prototype.toString = function() {
return 'bbb';
}
let a = {};
let b = +a;
let c = Number(a);
console.log(b);
console.log(c);
Вывод приведенного выше кодаNaN, это потому что мыtoStringметод возвращенbbbНет возможности преобразовать его в нормальное значение, принудительно преобразоватьNaN:
Определение типа
Обнаружение типов — это проблема, с которой мы часто сталкиваемся, и во время интервью часто задают различные типы методов обнаружения.Ниже приведены несколько наиболее часто используемых типов методов обнаружения.
typeof
Наиболее часто используемая проверка типовtypeofсейчас:
let a;
typeof a; // undefined
let b = true;
typeof b; // boolean
let c = 123;
typeof c; // number
let d = 'abc';
typeof d; // string
let e = () => {};
typeof e; // function
let f = {};
typeof f; // object
let g = Symbol();
typeof g; // symbol
instanceof
typeofСамый простой, но он может судить только об основном типе, если это объект, то он не может судить о том, что это за объект.instanceofМожно определить, является ли объект экземпляром определенного класса, это обнаружение фактически основано на объектно-ориентированной цепочке и цепочке прототипов.Для получения дополнительной информации о принципе instanceof вы можете прочитать эту статью. Вот пример:
let a = new Date();
a instanceof Date; // true
constructor
constructorПринцип тот же, что и в предыдущемinstanceofВроде как, тоже на основе объектной ориентации и цепочки прототипов. Если объект является экземпляром класса, то его прототипconstructorНа самом деле он тоже указывает на этот класс, мы можем судить о егоconstructorчтобы определить, является ли он экземпляром класса.Конкретный принцип также подробно объясняется в статье, упомянутой выше.. Или используйте приведенный выше пример:
let a = new Date();
a.constructor === Date; // true
использоватьconstructorОбратите внимание при оценке, если прототип наconstructorПри изменении это обнаружение может завершиться ошибкой, например:
function a() {}
a.prototype = {
x: 1
}
let b = new a();
b.constructor === a; // 注意这时候是 false
вышеfalseПричина в том, чтоconstructorЭто свойство на самом деле висит наa.prototypeНиже мы приводимa.prototypeПри присвоении значения оно фактически перезаписывает все предыдущиеprototype, который также охватываетa.prototype.constructor, В это время у него на самом деле вообще нет этого атрибута.Если у нас есть доступ к этому атрибуту, мы можем найти его только в цепочке прототипов, и мы найдем его в это время.Object:
Чтобы избежать этой проблемы, когда мы добавляем свойства в прототип, лучше всего не перезаписывать все целиком, а добавлять только те свойства, которые нам нужны.Вышеприведенное изменяется на:
a.prototype.x = 1;
Если вы должны покрыть все, не забудьте поставитьconstructorдобавить обратно:
a.prototype = {
constructor: a,
x: 1
}
duck-typing
duck-typingПеревод "утиный тип", название довольно странное, оно означает животное, если оно похоже на утку, ходит как утка и крякает как утка, то мы думаем, что это утка. Другими словами, мы судим о том, является ли он уткой, по его внешности и поведению, вместо того, чтобы точно определить, являются ли его гены уткой. Этот метод, конечно, не является строгим с научной точки зрения, но в некоторых случаях он эффективен. В языках программирования это означает, что объект имеет определенные свойства и методы, чтобы определить, является ли он тем объектом, который нам нужен. Например, некоторые библиотеки с открытым исходным кодом будут иметь следующий способ записи, чтобы определить, является ли объект массивом:
function isArray(object) {
return object !== null &&
typeof object === 'object' &&
'splice' in object &&
'join' in object
}
isArray([]); // true
Это делается для того, чтобы определить, является ли целевой объект массивом, определяя, содержит ли целевой объект методы, которые должен иметь массив. Это называется выглядеть как утка, и это утка. но у одного естьspliceа такжеjoinОбъект метода также может пройти этот тест, так что это не точно, а подходит только для некоторых сценариев.
Object.prototype.toString.call
Object.prototype.toString.callОн более точен и может использоваться для определения типа нативного объекта:
Object.prototype.toString.call(new Array()); // [object Array]
Object.prototype.toString.call(new Date()); // [object Date]
Этот метод возвращает[object XXX]Этот XXX является соответствующим названием конструктора. Но он может определить только местные объекты, оно бесполезно для пользовательских типов:
function a() {}
let b = new a();
Object.prototype.toString.call(b); // [object Object]
Вы можете видеть, что для пользовательских классовaслучайb, мы останавливаемся[object Object], вместо того, что мы ожидали[object a].
Некоторые нативные методы: Array.isArray, Number.isInteger.
Чтобы решить проблему определения типа, JS также вводит некоторые нативные методы для обеспечения поддержки, такие какArray.isArrayа такжеNumber.isIntegerЖдать.Array.isArrayМожет использоваться для проверки, является ли объект массивом:
Array.isArray([]); // true
Array.isArray(123); // false
Number.isIntegerМожет использоваться для проверки, является ли объект целым числом:
Number.isInteger(1); // true
Number.isInteger(-1); // true
Number.isInteger(-1.1); // false
Number.isInteger('aaa'); // false
Если есть нативный метод обнаружения, мы, безусловно, рекомендуем использовать нативный метод, но в настоящее время нативный метод не так многочислен и всеобъемлющ, и для определения типа часто используется предыдущий метод.
подраздел
На самом деле в JS нет идеального метода обнаружения всех типов, конкретный метод обнаружения требует от нас выбора и выбора в соответствии с реальной ситуацией. Вот краткое изложение нескольких методов:
Суммировать
- JS имеет два типа данных, примитивные типы и ссылочные типы. Ссылочные типы в основном являются объектами.
- когда мы используем
+логическое суждение или==Существует неявное преобразование типов. - Иногда неявные преобразования типов будут иметь неожиданные результаты.
===, вместо==. - Преобразование объектов в строки и числа может потребовать корректировки
valueOfа такжеtoStringметод, порядок вызова зависит от конкретной сцены. - В JS нет идеального метода определения типов, нам лучше выбрать конкретный метод определения в соответствии с нашими потребностями.
В конце статьи спасибо, что потратили свое драгоценное время на чтение этой статьи. Если эта статья немного поможет вам или вдохновит, пожалуйста, не скупитесь на лайки и звезды GitHub. Ваша поддержка является движущей силой для автор продолжать творить.
Добро пожаловать, чтобы обратить внимание на мой общедоступный номербольшой фронт атакиПолучите высококачественные оригиналы впервые~
Цикл статей "Передовые передовые знания":nuggets.capable/post/684490…
Адрес GitHub с исходным кодом из серии статей «Advanced Front-end Knowledge»:GitHub.com/Денис — см....