前言
在我们学习编程的时候,最先接触的就是数据类型了,每一种语言都是自己的数据类型,JavaScript 也不例外,JavaScript 的数据类型主要包括两种大的类型 基本类型 和 引用类型,接下来我们就来分析一下这两种类型的区别。
数据类型
基本类型
- Number 数字类型
- String 字符串类型
- Boolean 布尔类型
- Null null 类型
- undefined undefined 类型
引用类型
- Object 对象类型
两种的区别
基本类型的存储是存储在 栈 中,而引用类型的存储是在 堆 中,基本变量存储的是具体的值,而引用类型存储的是 堆中的地址,如下图所示
为什么基本类型与引用类型的存储方式不一致
- 堆比栈大,栈比对速度快。
- 基础数据类型比较稳定,而且相对来说占用的内存小。
- 引用数据类型大小是动态的,而且是无限的。
- 堆内存是无序存储,可以根据引用直接获取。
检测数据类型
检测类型的方法我们有 typeof、instanceof、Object.prototype.toString.call()等
- typeof 可以看到 typeof 可以检测出大部分的数据类型,function 类型也可以检测出来,缺陷是 null 和 Array 类型都检测出来是 object 类型,Array 是引用类型,检测出来是 object 类型是没有问题的,但是 null 出是 object 类型就是一个 bug 了,而且这个 bug 已经在 JavaScript 中存在很久了
console.log(typeof 2) // number
console.log(typeof '2') // string
console.log(typeof true) // boolean
console.log(typeof undefined) // undefined
console.log(typeof null) // object
console.log(typeof function() {}) // function
console.log(typeof []) // object
console.log(typeof {}) // object
- instanceof instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,缺陷是无法判断它的构造函数具体是哪个,可以使用 实例.proto.constructor === 构造函数 进行判断
class People {}
class Student extends People {}
let s = new Student
console.log(s instanceof Student) // true
console.log(s instanceof People) // true
console.log(s instanceof Object) // true
- Object.prototype.toString.call() 原理是使用 Object.prototype 上的原生 toString() 方法判断数据类型
// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true); // => "[object Boolean]"
// Number 类型,tag 为 "Number"
Object.prototype.toString.call(1); // => "[object Boolean]"
// String 类型,tag 为 "String"
Object.prototype.toString.call(""); // => "[object String]"
// Array 类型,tag 为 "String"
Object.prototype.toString.call([]); // => "[object Array]"
// Arguments 类型,tag 为 "Arguments"
Object.prototype.toString.call((function() {
return arguments;
})()); // => "[object Arguments]"
// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function(){}); // => "[object Function]"
// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error()); // => "[object Error]"
// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/); // => "[object RegExp]"
// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date()); // => "[object Date]"
// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new class {}); // => "[object Object]"