likes
comments
collection
share

JavaScript开发:数据类型知识总结

作者站长头像
站长
· 阅读数 14

本文以《JavaScript高级程序设计》第4版作为参考,整理使用JavaScript开发过程中,数据类型相关的知识点。

本文是开发知识点系列第二篇。

数据类型可以说是整个开发中的重中之重。没有数据什么都没法谈,有了数据也就有了数据类型。JavaScript数据类型有不同的分类标准,按照简单复杂分为简单数据类型和复杂数据类型,按照存储位置分为基本数据类型和引用数据类型。

简单数据类型和复杂数据类型

其中简单数据类型包含:

  • Boolean
  • Number
  • String
  • Undefined
  • Null
  • Symbol

其中Boolean只有truefalse两个值。

其中Number数据类型的最大值约为179,769,313,486,231,570,814,527,423,731,704,356,798,070,567,525,844,996,598,917,476,803,157,260,780,028,538,760,589,558,632,766,878,171,540,458,953,514,382,464,234,321,326,889,464,182,768,467,546,703,537,516,986,049,910,576。还是挺大的,最小值约为5e-324。确定有限大,即介于JavaScript能表示的最大值和最小值之间,可以使用isFinite()函数。

其中String数据类型的最大长度,根据ECMAScript标准,字符串的最大长度是2^53 - 1(即 9007199254740991)。

其中Undefined类型只有一个值,即undefined

其中Null类型只有一个值,即null

其中Symbol从ES6开始有。Symbol符号是原始值,且实例是唯一的不可变的,可以用来确保对象属性使用唯一标识符。

还有一种复杂数据类型叫Object(对象)。Object是一种无序名值对的集合,它是一种无序的数据结构,其中的属性(键)和对应的值是成对存在的。

基本数据类型和引用数据类型

在JavaScript中,基本数据类型的存储位置有两种情况:

  1. 栈(Stack):基本数据类型的值通常直接存储在栈内存中。栈是一种后进先出(LIFO)的数据结构,用于存储函数调用、局部变量和函数参数等。当一个函数被调用时,会在栈上创建一个新的执行上下文,并在其中存储函数的参数和局部变量。当函数执行完毕后,其执行上下文会从栈中弹出,释放相应的内存空间

  2. 固定内存空间:JavaScript中的基本数据类型(数字、字符串、布尔值、nullundefined)的值是固定的,它们的存储是直接在变量中分配的。这意味着基本数据类型的值直接存储在变量所分配的内存空间中

需要注意的是,基本数据类型的值是不可变的,即它们的值在创建后不能被修改。当对基本数据类型进行赋值或传递给函数时,实际上是将值复制到新的变量或参数中。

与基本数据类型不同,引用类型(包括对象、数组和函数)的值存储在堆内存中,并且变量中存储的是对象的引用。当对象被赋值给变量或作为参数传递时,实际上是将对象的引用复制到新的变量或参数中,而不是复制整个对象。这也是为什么对象是可变的,因为可以通过引用修改对象的属性和值。

正因为引用数据类型的特殊性,如果要判断引用数据类型(如对象和数组)的相等性需要注意以下几点:

  1. 引用相等性:引用数据类型的相等性判断是基于引用的比较。当两个变量引用的是同一个对象时,它们被认为是相等的。可以使用 === 运算符来判断两个引用是否指向同一个对象。
const obj1 = { name: "John" };
const obj2 = { name: "John" };
const obj3 = obj1;

console.log(obj1 === obj2); // 输出:false
console.log(obj1 === obj3); // 输出:true
  1. 值相等性:如果需要判断两个对象的值是否相等,需要根据对象的属性进行比较。可以编写自定义的比较函数来逐个比较对象的属性值。
function isEqual(obj1, obj2) {
  // 自定义比较逻辑,比较对象的属性值
  // 返回 true 或 false
}

const obj1 = { name: "John", age: 25 };
const obj2 = { name: "John", age: 25 };

console.log(isEqual(obj1, obj2)); // 输出:true

实际上,简单数据类型比如数字、字符串、布尔值也可以变为引用数据类型,只需要使用NumberStringBoolean声明即可。

const n = new Number(1)
const s = new String('s')
const b = new Boolean(true)
console.log(typeof n, typeof s, typeof b) // object object object

而直接使用字面量初始化时

const n = 1
const s = 's'
const b = true
console.log(typeof n, typeof s, typeof b) // number string bolean

2023年9月15日更新

通过typeof检测知道直接字面量初始化不是对象,然而其仍然具备了引用数据类型特性。这是因为后台进行了很多处理,具体步骤如下:

  1. 创建该类型的实例
  2. 调用实例上的特定方法
  3. 销毁实例

这样就让原始字面量拥有了引用数据类型的行为。

判断数据类型

typeof

typeof常用来判断数据类型,比如上面用以区分基本数据类型和引用数据类型。但typeof并不精准,就像将字面量初始化的字符串和new操作符初始化的字符串判断为两种类型。

而且typeof null也会返回object

instanceof

instanceof运算符用于检查对象是否属于特定的构造函数或类。它可以判断一个对象是否是某个类的实例。例如:obj instanceof Array判断obj是否是一个数组的实例。

Array.isArray

Array.isArray(value)方法用于检查一个值是否为数组。

Object.prototype.toString.call

Object.prototype.toString.call方法可以返回一个表示数据类型的字符串。它适用于所有的数据类型,并且返回的结果更具体。

let n1 = 1
let n2 = new Number(1)

console.log(Object.prototype.toString.call(n1), Object.prototype.toString.call(n2)) 
// 输出 [object Number] [object Number]

综上,Object.prototype.toString.call才是银弹,终极判断数据类型方案

/**
 * @desc 数据类型检测
 * @param data 待检测的数据
 * @return {String} 类型字符串
 */
function type(data) {
  return Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
}

用上面的方法先判断大类型,之后再判断小类型。当然其它用于检验数据类型的方法不是不可以用,而是要看具体的开发场景开放需求。

最后总结一下:

  1. 要注意区分基本数据类型和引用数据类型区别,和简单数据类型复杂数据类型有什么区别
  2. 区分Number数据类型边界,String类型最大长度
  3. Symbol符号的特点和作用
  4. 最佳判断数据类型的方案是Object.prototype.toString.call

本文完。

转载自:https://juejin.cn/post/7277471908416864293
评论
请登录