Преимущества и недостатки четырех методов определения типа данных в JS

JavaScript
Преимущества и недостатки четырех методов определения типа данных в JS

Для определения типа данных автор написал статью до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различие普通对象еще数组对象``...ждал
  • 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)
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значение данных, которое нужно обнаружить
  • 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);
}