JavaScript的变量和数据类型介绍

文章目录

  • [一、 变量声明:从 var 到 let 与 const 的进化](#一、 变量声明:从 var 到 let 与 const 的进化)
  • [二、 数据类型:两大阵营(原始类型 vs 引用类型)](#二、 数据类型:两大阵营(原始类型 vs 引用类型))
    • [1. 原始类型(栈内存存储,按值访问)](#1. 原始类型(栈内存存储,按值访问))
    • [2. 引用类型(堆内存存储,按引用访问)](#2. 引用类型(堆内存存储,按引用访问))
  • [三、 类型检测:三把"照妖镜"](#三、 类型检测:三把“照妖镜”)
  • [四、 类型转换:显式与隐式(双刃剑)](#四、 类型转换:显式与隐式(双刃剑))
  • [五、 知识图谱速查表(面试/实战高频)](#五、 知识图谱速查表(面试/实战高频))
  • [💡 给你的"避坑"与进阶建议](#💡 给你的“避坑”与进阶建议)

一、 变量声明:从 var 到 let 与 const 的进化

声明变量是第一步。JS主要提供了三种关键字,它们在作用域和提升(Hoisting) 行为上有本质区别。

核心要点解析

1、块级作用域

let 和 const 的出现,解决了 var 污染全局和循环变量泄露的问题。

bash 复制代码
if (true) {
    var a = 1;
    let b = 2;
}
console.log(a); // 输出 1(var 逃逸出了块级)
console.log(b); // 报错:b is not defined(let 被锁在块内)

2、暂时性死区(TDZ)

虽然 let 和 const 也会提升,但在声明之前访问它们会报 ReferenceError,这个声明到赋值之间的区域就是 TDZ。这强制你必须先声明,后使用,代码更健壮。

3、const 的"不变"误区

const 保证的是变量指向的内存地址不变。如果指向的是对象,对象的属性值是可以修改的。

bash 复制代码
const obj = { name: 'JS' };
obj.name = 'JavaScript'; // ✅ 允许,因为 obj 的引用没变
// obj = {}; // ❌ 报错,试图更改引用

二、 数据类型:两大阵营(原始类型 vs 引用类型)

JS 的数据类型分为原始类型(Primitive) 和引用类型(Object)。它们的存储方式和赋值机制完全不同。

1. 原始类型(栈内存存储,按值访问)

目前有 7 种原始类型。它们保存在栈内存中,赋值时是"复制一份值"。

number:双精度 64 位浮点数。包含整数和小数,以及特殊值 Infinity、-Infinity 和 NaN(Not a Number)。

注意:NaN 是唯一的 typeof NaN === 'number' 且 NaN !== NaN 的值,需用 Number.isNaN() 判断。

bigint(ES2020):用于表示大于 2^53 - 1 或小于 -(2^53 - 1) 的整数。写法:const big = 9007199254740991n;。

string:UTF-16 编码的字符序列。不可变,任何字符串操作都会返回一个新字符串。

boolean:true 和 false。

undefined:声明了变量但未赋值时的默认值。

null:表示"空"或"不存在"的对象指针(这也是著名的 typeof null === "object" 的历史遗留 Bug)。

symbol(ES6):保证唯一性的标识符,常用于定义对象的私有属性名或常量值。

2. 引用类型(堆内存存储,按引用访问)

Object(对象):一切复杂结构的基类。包括普通对象 {}、数组 \[\]、函数 function、日期 Date、正则 RegExp 等。

存储机制:变量名存储在栈中,指向堆内存中实际存储数据的内存地址。赋值时,只是复制了这个地址(引用),新旧变量指向同一个数据。

赋值对比(关键区别):

bash 复制代码
// 原始类型(独立副本)
let a = 10;
let b = a;
b = 20;
console.log(a); // 10 (互不影响)

// 引用类型(共享引用)
let obj1 = { value: 10 };
let obj2 = obj1;
obj2.value = 20;
console.log(obj1.value); // 20 (因为指向同一片内存)

三、 类型检测:三把"照妖镜"

由于动态类型,我们经常需要确认变量的类型。

实战最推荐:Array.isArray() 专门检测数组;判断空值用 === null 或 === undefined。

四、 类型转换:显式与隐式(双刃剑)

JS 的灵活性也体现在"自动类型转换"上,即隐式转换。

显式转换(手动控制,推荐)

转字符串:String(123) 或 (123).toString()

转数字:Number('456')、parseInt('123px')(解析)、+ 一元运算符

转布尔:Boolean(0) (返回 false)

隐式转换(自动发生,容易踩坑)

当使用 +、==、> 或 if 判断时,引擎会偷偷帮我们转换类型。

bash 复制代码
console.log('1' + 2);  // '12' (数字隐式转为字符串)
console.log('6' - 2);  // 4   (字符串隐式转为数字)
console.log(0 == false); // true (布尔转为数字)
console.log(0 === false); // false (严格相等,不转换类型,推荐使用)

最佳实践:除了比较 null 或 undefined 外,永远使用 =(全等) 和 !==,避免隐式转换带来的预料之外的结果。

五、 知识图谱速查表(面试/实战高频)

💡 给你的"避坑"与进阶建议

1、拥抱 let 和 const:在现代开发中,彻底放弃 var,这是公认的最佳实践。

2、操作不可变性:操作引用类型(对象/数组)时,若不想影响原数据,请使用展开运算符 ... 或 Object.assign() 创建浅拷贝;深拷贝需使用 structuredClone() 或 lodash.cloneDeep。

3、注意浮点数精度:0.1 + 0.2 !== 0.3,涉及金额计算请使用整数(分)或 BigInt。

4、内存泄露:引用类型因为"按引用访问",若全局变量持有了大对象的引用,且忘记释放,会导致内存泄露。记得在不需要时赋值为 null 来解除引用。

相关推荐
默_笙15 小时前
🍕 后端接口还没写好,前端已经跑起来了?Mock 数据 + axios 接口层,前后端再也不互相"等"
前端·javascript
爱勇宝16 小时前
客户只想看个页面,我却做了一个静态演示发布系统
前端·javascript·后端
ZJU_统一阿萨姆16 小时前
【算子开发】环境搭建与第一个CUDA程序
开发语言·人工智能·系统架构
Evand J16 小时前
【MATLAB例程,车联网8】MPC网联车辆节能跟驰控制:速度跟踪、间距约束与能耗优化。附MATLAB完整代码的下载链接
开发语言·matlab·车联网·调度·mpc·节能·车辆控制
ttwuai16 小时前
Go 后台接入 SSO 后菜单正常但接口 403,怎么排查权限链路?
开发语言·后端·golang
Canmag 兴隆磁性16 小时前
C 系列充磁机
c语言·开发语言·学习·永磁材料·充磁·退磁
benchmark_cc17 小时前
批量获取量化数据时,如何设置合理的超时和重试机制?——QuantDash 高性能实战指南
开发语言·人工智能·python·pandas·量化·quantdash
2601_9669496517 小时前
使用 Pandas 读取批量数据时如何避免内存溢出?QuantDash 量化数据工程师避坑指南
开发语言·python·pandas·tushare·akshare·quantdash
郑州光合科技余经理17 小时前
海外版多语言团购系统架构:主数据互通与核销边界
java·开发语言·前端·后端·系统架构·php·ai编程
ttwuai17 小时前
Go 后台图片上传到对象存储后,预览 403/404 怎么排查?
开发语言·golang