[JS]【二】[1]-- 基本数据类型、数据类型检测

221 阅读3分钟

基本数据类型

​ 包括基础(原始)数据类型 和引用(复杂)数据类型

原始数据类型(基本数据类型):

  1. 数值类型(Number): 整数和浮点数
  2. 字符串类型(String): 用引号括起来的
  3. 布尔类型(Boolean):true和false
  4. undefined类型:确定一个已经声明但还没有赋值的变量
  5. null类型:表明某个变量的值为空 (空对象指针)
  6. Symbol 类似于一种标识唯一性的ID Symbol 是独一无二的所以可以保证对象属性的唯一
  7. Bigint 可以表示任意大的整数 BigInt(value); value: 创建对象的数值。可以是字符串或者整数

引用数据类型(对象数据类型):

  1. 对象 :Object
  2. 数值 :Array
  3. 函数 :function

所有的引用数据类型数据的创建都要开辟一个【堆内存】

检测数据类型的方法有:

  1. typeof 用来检测数据类型的 【运算符】,【返回的结果是一个字符串】
  2. instanceof 用来检测当前实例是否属于某个类,【变相用来检测数据类型,看作是对typeof的补充
  3. constructor 基于构造函数检测数据类型,(也是基于类的方式)
  4. Object.prototype.toString.call([value]) 【检测数据类型的最好方法】

【运算符】typeof[val]

特点1:返回的结果是字符串,字符串中包含了对应的数据类型

typeof typeof typeof [1,2,3]  //面试题
  • 因为typeof检测的结果都是字符串,所以只要两个及以上同时检测,最后结果必然是"string"

特点2:按照计算机底层存储的二进制进行检测(实现原理)

  • 000 对象
  • 1 整数
  • 010 浮点数
  • 100 字符串
  • 110 布尔
  • 000000…. null
  • -2^30 undefined

特点3:typeof null -> “object” null的结果是object 因为 null 是0000000

特点4:typeof 对象 -> “object” && typeof 函数 -> “function”

  • 验证是否是对象的判断
  • 缺点:不能细分出具体为什么类型的对象 ,因为只要是对象数据类型,返回的结果都是"object"
  • typeof 数组/正则/日期/对象 【只要是对象数据类型】=>'object'

特点5:typeof 未被声明的变量 -> “undefined”

  • 插件封装中的暴露API
//【对于基本数据类型】
let a = NaN;
typeof 1;//=>"number"
typeof a;//=>"number"
typeof NaN;;//=>"number"
typeof 'string';//=>"string"
typeof true;//=>"boolean"
typeof undefined;//=>"undefined"
typeof null;//"object"
typeof typeof undefined;//=>"string"

//【对于引用数据类型】
typeof {};//=>"object"
typeof [];//=>"object"
typeof /^/;//=>"object"
typeof function(){};//=>"function"
typeof typeof typeof function(){};//=>"string"

【运算符】instanceof

instance运算符用于通过查找原型链来检测某个变量是否为某个类型数据的实例。使用instanceof 运算符可以判断一个变量时数组还是对象。

【缺陷】:

  • 不能用来处理基本数据类型**(基本数据类型基于构造函数方式创建的实例是可以的)**

  • 只要出现在实例的原型链上的类,该实例的检测结果都是true**(可以手动更改原型链的指向,这样导致检测结果不一定准确)

let arr = [],
reg = /^$/;
const b = {name: 'xx'};
console.log(arr instanceof Array);//=>true
console.log(arr instanceof Object);//=>true
console.log(b instanceof Array); // false
console.log(b instanceof Object); // true
console.log(reg instanceof Array);//=>false

console.log(1 instanceof Number);//=>false
console.log(new Number(1) instanceof Number);//=>true
console.log(Symbol() instanceof Symbol);//=>false

function fn(){}
fn.prototype = Array.prototype;
let f = new fn;
console,log(f instanceof Array);//=>true

constructor: 基于构造函数检测数据类型

constructor主要是利用原型上的prototype.constructor指向实例的构造函数来进行判断的

null, undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。

函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object

  • constructor 判断类型的限制过多且不准确,容易出错,少用,或者不用!
const a = [0, 1, 2];
console.log(a.constructor === Array); // true
console.log(a.constructor === Object);  // false

const b = {name: 'xx'};
console.log(b.constructor === Array); // false
console.log(b.constructor === Object); // true

console.log('1'.constructor === String);  // true
console.log(new Number(1).constructor === Number); // true
console.log(true.constructor === Boolean); // true
console.log(alert.constructor === Function); // true
console.log([].constructor === Array); // true
console.log(new Date().constructor === Date); // true

Object.prototype.toString.call():【检测数据类型的最好方法】

每种引用类型都会直接或者间接继承自Object类型,因此它们都包含toString()函数。不同数据类型的toString()类型返回值也不一样,所以通过toString()函数可以准确判断值的类型。

  • object.prototype.toString执行,他中的this是谁,就是检测谁的数据类型
  • object.prototype.toString.call(xxx) 若要检测其他类实例,则要改变this指向
  • 相当于({}).toString.call(xxx)

最强大的检测数据类型的方法,(基本上没有弊端)

  • 对于 number 类型,结果是 [object Number]

  • 对于 boolean 类型,结果是 [object Boolean]

  • 对于 null:[object Null]

  • 对于 undefined:[object Undefined]

  • 对于数组:[object Array]

  • 对于对象:[object Object]

  • ……等(可自定义)

    object.prototype.toString.call(null) //"[object Null]"
    object.prototype.toString.call(1)// "[object Number]"
    object.prototype.toString.call(new Number(1)) //"[object Number]"
    object.prototype.toString.call(Symbol()) //"[object Symbol]"
    object.prototype.toString.call(function(){}) //"[object Function]"
    object.prototype.toString.call(Object) //"[object Function]"
    object.prototype.toString.call({}) //"[object Object]"
    object.prototype.toString.call([]) //"[object Array]"
    object.prototype.toString.call(/^$/) //"[object RegExp]"
    object.prototype.toString.call(new Date()) //"[object Date]"
    
    function fn(){}
    let f = new fn();
    
    object.prototype.toString.call(f);//=>'[object object]'