一、数据类型的修罗场
在JavaScript的江湖里,变量们被划分为两大阵营:
1. 简单类型(钢铁直男团)
成员档案:
- Number:数学系高材生,但0.1+0.2≠0.3是他的毕生污点
- String:文字艺术家,擅长用反引号写诗
- Boolean:非黑即白的二极管,人生只有true/false
- Null:已注销的空账号,typeof检测显示"object"是系统bug
- Undefined:薛定谔的变量,未被定义的量子态
- Symbol:防伪标识专家,每个实例都是全球唯一
- BigInt:数学界的姚明,专门处理天文数字
生存法则:
javascript
let a = 42; // 在栈内存开单人间
let b = a; // 克隆体诞生
b = 100; // 本体毫发无损
2. 复杂类型(海王俱乐部)
入会资格:
- Object:万恶之源,所有引用类型的教父
- Array:伪装成数组的对象,length属性会骗人
- Function:拥有[[Call]]技能的变形金刚
- Date:永远在和时间较劲的强迫症患者
社交方式:
javascript
const obj1 = { name: '小明' }; // 在堆内存买豪宅
const obj2 = obj1; // 共享房产证
obj2.name = '大明'; // 全小区都知道改名了
二、内存分配的潜规则
1. 栈内存:快捷酒店
- 入住条件:固定大小的简单类型
- 生存周期:随用随走,退房即销毁
- 服务特色:快速存取,但房间不能扩建
graph LR
A[变量声明] --> B[分配栈内存]
B --> C[存储原始值]
C --> D[使用后立即回收]
2. 堆内存:豪华公寓
- 住户特征:动态扩容的复杂类型
- 管理模式:地址门牌号存在栈里
- 安全隐患:容易造成内存泄漏(像永远不退租的房客)
javascript
// 经典内存泄漏现场
function createLeak() {
const hugeObj = new Array(1e6).fill('内存');
return function() {
console.log(hugeObj[0]); // 闭包强行续命
};
}
三、类型检测的宫斗戏
1. typeof的塑料姐妹花
javascript
console.log(typeof 42); // "number"
console.log(typeof '字符串'); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 9007199254740993n); // "bigint"
// 著名翻车现场
console.log(typeof null); // "object"(千古奇冤)
console.log(typeof [1,2,3]); // "object"(数组の泪)
console.log(typeof function(){}); // "function"(特殊优待)
2. 终极裁判官:Object.prototype.toString
javascript
const typeDetective = obj => {
return Object.prototype.toString.call(obj)
.replace(/\[object (\w+)\]/, '$1')
.toLowerCase();
};
console.log(typeDetective(null)); // "null"
console.log(typeDetective([])); // "array"
console.log(typeDetective(new Set)); // "set"
四、引用类型的七十二变
1. 函数:会代码的变形金刚
javascript
function ninja() {
return '忍者技能';
}
// 对象化形态
ninja.weapon = '手里剑';
ninja.attack = () => console.log('发动奥义!');
// 间谍模式
const spy = new ninja(); // [[Construct]]启动
2. 数组:伪装的列表
javascript
const arr = ['a', 'b', 'c'];
// 对象本质暴露
arr['秘密属性'] = '我是对象';
console.log(arr.length); // 3(装傻充愣)
console.log(arr[3]); // undefined(继续伪装)
五、数据江湖生存指南
1. 拷贝与引用的罗生门
操作类型 | 典型场景 | 风险指数 |
---|---|---|
浅拷贝 | Object.assign | ★★★☆☆ |
深拷贝 | JSON.parse(JSON.stringify()) | ★★☆☆☆ |
引用传递 | 直接赋值对象 | ★★★★★ |
防坑口诀:
简单类型传值,复杂类型传址
对象操作要三思,克隆记得用深拷
2. 类型转换的玄学
javascript
console.log([] + {}); // "[object Object]"
console.log({} + []); // 0
console.log(Boolean([]));// true(空数组不空)
console.log(Number({})); // NaN(对象无法量化)
六、武林秘籍:特殊类型冷知识
1. Null的身份证疑云
javascript
typeof null === 'object' // 历史遗留bug
// 原理:二进制前三位000判定为对象,而null是全0...
2. Symbol的防伪技术
javascript
const symbol1 = Symbol('身份证');
const symbol2 = Symbol('身份证');
console.log(symbol1 === symbol2); // false(克隆人战争)
3. BigInt的数学革命
javascript
console.log(1n + 2n); // 3n
console.log(1n == 1); // true
console.log(1n === 1); // false(严格模式不妥协)
七、终极思考:为什么typeof typeof是"string"?
javascript
console.log(typeof typeof 42); // "string"
这个哲学问题,留给屏幕前的你来解答...(答案藏在操作符的隐式转换中)