Для определения типа данных автор написал статью доtypeofизМетод определения типа данных в JS — typeof, сегодня я разберу разницу между четырьмя методами определения типа данных в JS:
-
tyepof [value]: оператор для определения типа данных -
[example] instanceof [class]: проверить, принадлежит ли экземпляр к этому классу -
[example].constructor===[class]: Обнаружение отношений экземпляра и класса, тем самым определяя типы данных. -
Object.prototype.toString.call([value]): Определить тип данных
1. тип
- 1. Определение: операторы, используемые для определения типов данных.
- 2. Грамматика:
tyepof [value] - 3. Возвращаемое значение:
-
typeofРезультатом обнаружения является сначала строка; - Строка содержит соответствующий тип данных (например:
“number”,“string”,“boolean”,“undefined”,“object”,“function”,“symbol”,“bigint”)
-
- 4. Преимущества: простота использования, основные значения типов данных могут быть эффективно обнаружены, а также могут быть обнаружены значения эталонных типов данных.
- 5. Ограничения (специальные значения)
- 1),
NaN/Infinityвсе числовые типы, а результаты теста“number”; - 2),
typeof nullРезультат“object”;- (это браузер
BUG: Все значения сохраняются в двоичной кодировке при расчете, первые три цифры сохраняются в браузере000как предмет иnullПервые три бита в двоичном коде000, так что он распознается как объект, но он не объект, он нулевой указатель объекта, значение базового типа)
- (это браузер
- 3),
typeof普通对象/数组对象/正则对象..., результат“object”, на котором нельзя основыватьсяtypeofразличие普通对象еще数组对象``...ждал
- 1),
- 6. Сценарии применения
- Известно, что есть переменная х, но мы не можем подтвердить ее тип данных, нам нужна операция суждения: когда тип х является объектом (любой объект может быть), то иметь дело с соответствующей вещью
if (typeof x == "object") {
//=>null检测结果也会是"object",所以结果是"object"不一定是对象,还可能是null呢
...
}
Вы можете использовать условия 👇, чтобы судить
if (x != null && typeof x == "object") {
// ...
}
- 7. Практические вопросы
console.log(typeof []); //=>"object"
console.log(typeof typeof typeof []); //=>"string"
Примечание:
Поскольку результат, возвращаемый typeof, всегда является строкой (строка содержит соответствующий тип), когда подряд появляются два или более теста typeof, конечным результатом будет `string'.
2. экземпляр
- 1. Определение: используется для определения принадлежности экземпляра к этому классу.
- Прототип текущего класса возвращается до тех пор, пока он появляется в цепочке прототипов экземпляра.
true
- Прототип текущего класса возвращается до тех пор, пока он появляется в цепочке прототипов экземпляра.
- 2. Грамматика:
实例 instanceof 类 - 3. Принадлежат к возврату
TRUE, не является частью возвратаFALSE - 4. Преимущества:
- Таким образом можно компенсировать
typeofНедостаток невозможности разделить тип объекта (если вы хотите определить, является ли значение массивом, вам нужно только увидеть, является ли оно экземпляром класса Array)
- Таким образом можно компенсировать
let arr = [10, 20];
console.log(typeof arr); //=>"object"
console.log(arr instanceof Array); //=>true
console.log(arr instanceof RegExp); //=>false
console.log(arr instanceof Object); //=>true 不管是数组对象还是正则对象,都是Object的实例,检测结果都是TRUE,所以无法基于这个结果判断是否为普通对象
- 5. Ограничения:
- 1), экземпляр, который требуется обнаружить, должен иметь тип данных объекта
- 2), экземпляр базового типа данных не может быть обнаружен на его основе
- Буквально созданный не может быть обнаружен
- Созданный конструктор может обнаруживать
- 3), является ли это объектом массива корейским обычным объектом, является ли он экземпляром объекта, и результат обнаружения ИСТИНА, поэтому невозможно судить, является ли это обычным объектом на основе этого результата.
// instanceof检测的实例必须都是引用数据类型的,它对基本数据类型值操作无效
console.log(10 instanceof Number); //=>false
console.log(new Number(10) instanceof Number); //=>true
// instanceof检测机制:验证当前类的原型prototype是否会出现在实例的原型链__proto__上,只要在它的原型链上,则结果都为TRUE
function Fn() {}
Fn.prototype = Object.create(Array.prototype);
let f = new Fn;
console.log(f instanceof Array); //=>true f其实不是数组,因为它连数组的基本结构都是不具备的
Примечание️: Он не может выполнить определение типа данных сам по себе, а только использует свои функции (определение принадлежности экземпляра к этому классу) для завершения обнаружения данных.
Три, конструктор
- 1. Определение: судить о текущем экземпляре
constructorЭто значение свойства предполагаемого класса (используя его обнаружение типа данных экземпляра) - 2. Грамматика:
实例.constructor === 类 - 3. Возвращаемое значение: принадлежит возврату
TRUE, не является частью возвратаFALSE - 4. Преимущества:
-
实例.constructorобычно равно类.prototype.constructorТо есть сам текущий класс (при условии, что вашconstructorи не уничтожен) - Может обнаруживать основные типы данных
-
- 5. Ограничения:
- 1) Невозможность перенаправить прототип текущего класса приведет к неточным результатам обнаружения (
Object) - 2), не может добавлять частные свойства к текущему экземпляру
constructor, это также приведет к неточным результатам обнаружения (Object) - 3), очень легко модифицировать, потому что
JSсерединаconstructorне защищен (пользователь может изменить его по своему усмотрению), поэтому на основеconstructorЕсть неопределенность в обнаруженном значении (но в проекте принципиально никто не будет менять встроенный классconstructor)
- 1) Невозможность перенаправить прототип текущего класса приведет к неточным результатам обнаружения (
let arr = [],
obj = {},
num = 10;
console.log(arr.constructor === Array); //=>true
console.log(arr.constructor === Object); //=>false
console.log(obj.constructor === Object); //=>true
console.log(num.constructor === Number); //=>true
Примечание. Он не может выполнить определение типа данных сам по себе, используйте определение типа данных своего экземпляра (не может перенаправлять)
4. Object.prototype.toString.call()
Этот метод находится на прототипе Object
- 1. Определение: найти
Object.prototypeВверхtoStringметод, пустьtoStringметод выполняется и основан наcallпусть в методthisУказывает на обнаруженное значение данных, чтобы можно было реализовать обнаружение типа данных. - 2. Принцип:
- 1. Прототип конструктора каждого типа данных имеет
toStringметод; - 2. Кроме
Object.prototypeВверхtoStringОн используется для возврата информации о классе, к которому принадлежит текущий экземпляр (определение типа данных), а остальные преобразуются в строки. - 3.
对象实例.toString():toStringв методеTHISявляется экземпляром объекта, то есть для определения его типа данных, т.е.THISКто есть, тип данных чьего обнаружения - 4.
Object.prototype.toString.call([value])Итак, мы положилиtoStringвыполнять, исходя изcallИзменятьthisзначение данных, которое нужно обнаружить
- 1. Прототип конструктора каждого типа данных имеет
- 3. Как использовать:
- Object.prototype.toString.call (экземпляр обнаружен)
- ({}).toString.call(экземпляр обнаружен)
Object.prototype.toString.call(10)
({}).toString.call(10)
({}).toString===Object.prototype.toString
- 4. Возвращаемое значение:
- представляет собой строку «[класс, к которому принадлежит текущий обнаруженный экземпляр объекта]»
let class2type = {};
let toString = class2type.toString; //=>Object.prototype.toString
console.log(toString.call(10)); //=>"[object Number]"
console.log(toString.call(NaN)); //=>"[object Number]"
console.log(toString.call("xxx")); //=>"[object String]"
console.log(toString.call(true)); //=>"[object Boolean]"
console.log(toString.call(null)); //=>"[object Null]"
console.log(toString.call(undefined)); //=>"[object Undefined]"
console.log(toString.call(Symbol())); //=>"[object Symbol]"
console.log(toString.call(BigInt(10))); //=>"[object BigInt]"
console.log(toString.call({xxx:'xxx'})); //=>"[object Object]"
console.log(toString.call([10,20])); //=>"[object Array]"
console.log(toString.call(/^\d+$/)); //=>"[object RegExp]"
console.log(toString.call(function(){})); //=>"[object Function]"
- 5. Преимущества:
- Метод, специально используемый для обнаружения типов данных, в основном нет ограниченного метода определения типа данных.
- На его основе он может эффективно определять значение любого типа данных.
- 6. Ограничения:
- 1), может обнаруживать только встроенные классы, а не пользовательские классы
- 2), если пользовательский класс возвращает «[Object Object]»
Примечание. Этот метод основан на самом JS для обнаружения данных, поэтому в настоящее время это лучший способ обнаружения типов данных.
карта разума
Метод на основе определения типа данных в JQ — самоинкапсуляция
Для определения типа данных в JQ основное понимание автора заключается в использованииObject.prototype.toString.call()способ, так сказатьObject.prototype.toString.call()Может завершить принципиальный анализ определения типа данных;
function toType(obj) {
let class2type = {},
toString = class2type.toString, //=>Object.prototype.toString 检测数据类型
arr = "Boolean Number String Function Array Date RegExp Object Error Symbol".split(" ");
arr.forEach(item => {
class2type["[object " + item + "]"] = item.toLowerCase();
})
/*
console.log(class2type);
{
[object Boolean]: "boolean",
[object Number]: "number",
[object String]: "string"
......
}
*/
//传递给我的是null/undefined,直接返回 "null"/"undefined"
if (obj == null) {
return "" + obj;
}
// typeof obj === "object" || typeof obj === "function" =>引用数据类型
// => 如果是基本数据类型值,检测数据类型使用typeof就可以
// => 如果是引用数据类型值,则基于对象的toString就可以
// => toString.call(obj) 检测当前值的数据类型 "[object Xxx]"
// => class2type["[object Xxx]"] 当上一步生成的对象中,基于对应的属性名,找到属性值(所属的数据类型),如果没有则返回 "object"
return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" : typeof obj;
};
console.log(toType(1)); //=>"number"
console.log(toType(NaN)); //=>"number"
console.log(toType([])); //=>"array"
console.log(toType(/^\d+$/)); //=>"regexp"
console.log(toType({})); //=>"object"
console.log(toType(null)); //=>"object"
console.log(toType()); //=>"object"
Мы описали преимущества и недостатки четырех методов определения типа данных выше;
мы упоминали вObjectна прототипеtoStringметод, кстати, вот еще один вObjectна прототипеvalueOfметод
Разрозненные знания:Objectна прототипеvalueOfметод
Прототип конструктора каждого типа данных имеет
toStringметод;Прототип конструктора каждого примитивного типа данных имеет
valueOfметод;Object.prototypeПрототип также имеетvalueOfметод;
Основные типы данных:
- valueOf: получить исходное значение [[PrimitiveValue]]
- toString: преобразовать исходное значение в строку
let num1 = 10,
num2 = new Number(10);
console.log(num1);//=> 10
console.log(num1.valueOf());//=> 10
console.log(num1.toString());//=> "10"
console.log(num2);//=>Number {10}
console.log(num2.valueOf());//=> 10
console.log(num2.toString());//=> "10"
ссылочный тип данных
- В массиве:
Как было сказано выше, только прототипы конструкторов базовых типов данных имеютvalueOfметод;Object.prototypeПрототип также имеетvalueOfметод;
Так вот прототип конструктора массива не имеет этого метода, мы используем массив для вызоваvalueOfметод, который фактически находится через цепочку прототипов массиваObject.prototypeНа прототипе звонитеvalueOfМетоды;
let arr = [10, 20],
obj = {
xxx: 'xxx'
};
console.log(arr);
console.log(arr.valueOf()); //=>调取的是 Object.prototype.valueOf 原始值
console.log(arr.toString()); //=>调取的是 Array.prototype.toString 转换字符串
console.log(obj);
console.log(obj.valueOf()); //=>调取的是 Object.prototype.valueOf 原始值
console.log(obj.toString()); //=>调取的是 Object.prototype.toString 检测数据类型
Приложение — неявное преобразование
let num1 = 10,
num2 = new Number(10);
let arr = [10, 20],
obj = {
xxx: 'xxx'
};
Например:
ALERTВсе выходные значения будут преобразованы в строку (неявное преобразование), такие как неявные преобразованные в строку многих, например: строковые конкатенации, для преобразования цифрового объекта (преобразуется в строку) ...
- => num1.valueOf() сначала получить исходное значение
- =>[[PrimitiveValue]].toString() Преобразование полученного примитивного значения в строку
- Используя этот механизм, мы можем сделать вопрос интервью
Вопросы для интервью: a == 1 && a == 2 && a == 3
Оригинальное название выглядит следующим образом:
//=> 下面代码a在什么值情况下会输出1
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}
Одним из способов решения проблемы является использованиеvalueOfполучить исходное значение
var a = {
n : 0,
valueOf(){
return ++this.n;
}
};
if (a == 1 && a == 2 && a == 3) {
console.log(1);
}