探究js数据类型和底层原理
创始人
2024-02-09 12:17:49
0

数据类型

JS 的数据类型分为:基本数据类型和引用类型

  1. 数字(number)
  2. 字符串(string)
  3. 空值(null)
  4. 未定义(undefined)
  5. 布尔值(boolean)
  6. 符号(symbol, ES6 中新增)
  7. 大整数(BigInt, ES2020 引入)
  8. 对象 (object)

其中基本数据类型存放在栈内存中,引用类型存放在堆内存中

  • :原始数据类型(Undefined、Null、Boolean、Number、String、symbol、BigInt)
  • :引用数据类型(对象、数组和函数)

两种类型的区别在于 存储位置的不同

  • 栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
  • 堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:

数据结构中:

  • 栈中数据的存取方式为先进后出。
  • 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。

操作系统中,内存被分为栈区和堆区:

  • 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收

如何判断数据类型

  1. typeof

    typeof基本数据类型function 判断是准的,但对于 []、object 和 null就会判断成object

    console.log(typeof 2);           //number
    console.log(typeof NaN);         //number
    console.log(typeof "2");         //string
    console.log(typeof true);        //boolean
    console.log(typeof undefined);   //undefined
    console.log(typeof 123n);        //bigint
    console.log(typeof Symbol('张三'));  // symbol
    console.log(typeof function () {}); //functionconsole.log(typeof []); //object
    console.log(typeof {}); //object
    console.log(typeof null); //object

    那么,typeof 是根据什么判断的呢?

    在 JavaScript 第一个版本中,所有值都存储在 32 位的单元中,每个单元包含一个小的 类型标签(1-3 bits) 以及当前要存储值的真实数据。类型标签存储在每个单元的低位中,共有五种数据类型:

    码值类型
    000对象
    010浮点数
    100字符串
    110布尔
    1整数

    有两种特殊数据类型:

    • undefined的值是 (-2)30(一个超出整数范围的数字);
    • null 的值是机器码 NULL 指针(null 指针的值全是 0)

    那也就是说 null 的类型标签也是 000,和 Object 的类型标签一样,所以会被判定为 Object。所以 typeof null 的结果是 object。

  2. instanceof

    instanceof对引用类型的判断是准确的,对于基本数据类型都是 false.

    console.log(2 instanceof Number);       // false
    console.log(NaN instanceof Number);     // false
    console.log("2" instanceof String);     // false
    console.log(true instanceof Boolean);   // false
    console.log(Symbol('张三') instanceof Symbol);      // falseconsole.log(Object instanceof Object);              // true
    console.log(function () {} instanceof Function);    // true
    console.log([] instanceof Array);                   // true
    

    如何实现instanceof ?

    function myInstanceof(left, right) {// 获取对象的原型let proto = Object.getPrototypeOf(left)// 获取构造函数的 prototype 对象let prototype = right.prototype;// 判断构造函数的 prototype 对象是否在对象的原型链上while (true) {if (!proto) return false;if (proto === prototype) return true;// 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型proto = Object.getPrototypeOf(proto);}
    }
    
  3. constructor

    一般的数据类型和引用的都可以判断,但是 undefined 和 null 除外

    	console.log(('').constructor == String)console.log((true).constructor == Boolean)console.log(({}).constructor == Object)console.log(([]).constructor == Array)console.log((undefined).constructor == undefined)   //报错console.log((null).constructor == null)  //报错

但是注意,constructor 是可以被改变的。

  1. Object.prototype.toString.call()

    可以判断任何数据类型。
    原理:使用 Object 对象的原型方法 toString 来判断数据类型:

    var a = Object.prototype.toString;console.log(a.call(2));                 // [object Number]
    console.log(a.call(true));              // [object Boolean]
    console.log(a.call('str'));             // [object String]
    console.log(a.call([]));                // [object Array]
    console.log(a.call(function () {}));    // [object Function]
    console.log(a.call({}));                // [object Object]
    console.log(a.call(undefined));         // [object Undefined]
    console.log(a.call(null));              // [object Null]

    同样是检测对象 obj 调用 toString 方法,obj.toString()的结果和 Object.prototype.toString.call(obj)的结果不一样,这是为什么?

    这是因为 toString 是 Object 的原型方法,而 Array、function 等类型作为 Object 的实例,都重写了 toString 方法。不同的对象类型调用 toString 方法时,根据原型链的知识,调用的是对应的重写之后的 toString 方法(function 类型返回内容为函数体的字符串,Array 类型返回元素组成的字符串…),而不会去调用 Object 上原型 toString 方法(返回对象的具体类型),所以采用 obj.toString()不能得到其对象类型,只能将 obj 转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用 Object 原型上的 toString 方法。

  2. 原型链

    obj.__proto__ === Array.prototype; // true
    
  3. 通过 isPrototypeOf

    Array.prototype.isPrototypeOf(obj)
    

数组判断类型

  1. 通过 ES6 的 Array.isArray()做判断

    Array.isArrray(obj);
    
  2. 通过 instanceof 做判断

    obj instanceof Array
    
  3. 通过 Object.prototype.toString.call()做判断

    Object.prototype.toString.call(obj).slice(8,-1) === 'Array';
    
  4. 通过原型链做判断

    obj.__proto__ === Array.prototype;
    
  5. 通过 Array.prototype.isPrototypeOf

    Array.prototype.isPrototypeOf(obj)
    

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...