加载笔记内容...
加载笔记内容...
JavaScript 的类型系统以 值类型(Primitive Types) 和 引用类型(Reference Types) 为基本划分,这种二分法直接决定了变量在内存中的存储方式和操作特性:
值类型七剑客:
undefined
:未定义值的特殊标记null
:空对象指针boolean
:逻辑实体(true/false)number
:双精度浮点数(64位 IEEE 754)string
:UTF-16 编码的字符序列bigint
:任意精度整数(ES2020)symbol
:唯一且不可变的值(ES2015)引用类型三巨头:
Object
:所有对象的基类Array
:有序数据结构Function
:可执行对象
(图示:栈内存存储基本类型值,堆内存存储对象,变量保存对象引用地址)
typeof 运算符的陷阱与妙用:
1typeof "" // "string"
2typeof 42 // "number"
3typeof true // "boolean"
4typeof undefined // "undefined"
5typeof Symbol() // "symbol"
6typeof 42n // "bigint"
7typeof null // "object" (历史遗留问题)
8typeof [] // "object"
9typeof {} // "object"
10typeof console.log // "function"
instanceof 的继承链检测:
1class MyArray extends Array {}
2const arr = new MyArray();
3arr instanceof Array // true
4arr instanceof Object // true
5arr instanceof MyArray // true
栈内存(Stack):
堆内存(Heap):
闭包的内存特征:
1function createCounter() {
2 let count = 0; // 本应在栈中,闭包使其进入堆
3 return () => ++count;
4}
5const counter = createCounter();
6// count 变量被闭包引用,长期驻留堆内存
JavaScript 引擎使用 隐藏类(Hidden Class) 优化对象访问:
1// V8 对象内存布局示例
2+-------------------+
3| Hidden Class |
4| Map |
5+-------------------+
6| Properties |
7| 指针 |
8+-------------------+
9| Elements |
10| 指针 |
11+-------------------+
V8 使用 指针标记(Pointer Tagging) 技术:
undefined
: 0x7anull
: 0x001// 32位系统示例
2const num = 42; // 0x0000002a (最后一位1表示Smi)
3const obj = {}; // 0x12345670 (最后一位0表示指针)
Symbol 的独特性:
BigInt 的存储策略:
安全类型检测方案:
1function getType(value) {
2 return Object.prototype.toString.call(value)
3 .slice(8, -1)
4 .toLowerCase();
5}
6
7getType([]) // 'array'
8getType(null) // 'null'
深拷贝实现策略:
1function deepClone(obj) {
2 if (obj === null || typeof obj !== 'object') return obj;
3 const clone = Array.isArray(obj) ? [] : {};
4 for (const key in obj) {
5 if (obj.hasOwnProperty(key)) {
6 clone[key] = deepClone(obj[key]);
7 }
8 }
9 return clone;
10}
largeObject = null
Record & Tuple 提案(Stage 2):
1const record = #{
2 name: "Alice",
3 profile: #{ age: 30 }
4};
5const tuple = #[1, 2, #{ a: 3 }];
1function change(a, b) {
2 a = 10;
3 b.prop = 20;
4}
5
6let x = 1;
7let y = { prop: 2 };
8change(x, y);
9console.log(x, y.prop); // 1, 20
解析:
隐式转换优先级:
1const obj = {
2 valueOf: () => 42,
3 toString: () => '28'
4};
5console.log(obj + 1); // 43
1// 不同 iframe 中的数组检测
2const iframe = document.createElement('iframe');
3document.body.appendChild(iframe);
4const iframeArray = window.frames[0].Array;
5
6const arr = new iframeArray(1,2,3);
7console.log(arr instanceof Array); // false
8console.log(Array.isArray(arr)); // true
解决方案:优先使用 Array.isArray()
随着 WebAssembly 的普及和类型化数组的广泛应用,JavaScript 的类型系统正在向更严格、更高效的方向发展。ECMAScript 提案中的装饰器、模式匹配等特性,将进一步丰富类型系统的表达能力。工程师需要:
graph TD A[JavaScript 类型系统] --> B[值类型] A --> C[引用类型] B --> D[栈内存存储] B --> E[直接访问] C --> F[堆内存存储] C --> G[引用访问] D --> H[固定大小] F --> I[动态分配] E --> J[快速访问] G --> K[间接访问] H --> L[自动回收] I --> M[GC管理]
(类型系统关系图:展示值类型与引用类型的存储和访问特性)
通过深入理解这些核心概念,开发者可以写出更高效、更健壮的 JavaScript 代码,在复杂应用中游刃有余地处理各种类型相关问题。