JS较底层的用法
在 JavaScript 中,“偏底层”的用法通常是指更接近语言核心、规范、底层机制的特性。这些用法不是日常开发中最常见的,但对理解语言原理、优化性能或构建框架、库非常重要。下面是一些常见的“偏底层”用法或特性
1. 对象属性底层操作:Object.defineProperty()
可以定义属性的细粒度行为(是否可枚举、是否可写、是否可配置)
const obj = {};
Object.defineProperty(obj, 'hidden', {value: 'secret',enumerable: false,writable: false,configurable: false
});
2. 原型链控制:Object.create() 和手动设置 proto
const proto = { greet() { console.log('hi'); } };
const obj = Object.create(proto);
obj.greet();
3. 拦截对象操作:Proxy 和 Reflect
const target = {};
const proxy = new Proxy(target, {get(obj, prop) {console.log(`访问属性 ${prop}`);return Reflect.get(obj, prop);}
});proxy.name = 'Alice';
console.log(proxy.name);
4. 函数底层机制:call, apply, bind
function greet() {console.log(this.name);
}const user = { name: 'Tom' };
greet.call(user);
5. 作用域与闭包底层实现
function counter() {let count = 0;return function () {return ++count;}
}const c = counter();
c();
c();
6. 底层类型判断:Object.prototype.toString.call()
Object.prototype.toString.call([]);
Object.prototype.toString.call(null);
Object.prototype.toString.call(() => {});
7. 字节操作:ArrayBuffer, DataView, TypedArray
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
view.setInt32(0, 123456);
console.log(view.getInt32(0));
8. Symbol 和隐藏属性
const secret = Symbol('secret');
const obj = {[secret]: 'hidden value'
};
console.log(Object.keys(obj));
9. 执行上下文与事件循环分析(例如微任务 vs 宏任务)
console.log('start');setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));console.log('end');
10. 底层数据结构:Map, Set, WeakMap, WeakSet
当然!Map、Set、WeakMap、WeakSet 是 ES6 引入的底层数据结构,用于增强 JavaScript 的数据管理能力。它们解决了对象属性只能是字符串/符号、数组去重困难、内存泄漏风险等问题。以下是这四种结构的详细讲解和对比:
🗺️ Map:键值对集合(key-value)
特点
- 键可以是任意类型(对象、函数、基本类型)
- 按插入顺序迭代
- 通常用于替代普通对象作为字典
常用方法
方法 | 描述 |
---|
set(key, value) | 添加键值对 |
get(key) | 获取值 |
has(key) | 是否存在该键 |
delete(key) | 删除键值对 |
clear() | 清空所有条目 |
size | 当前条目数量 |
示例
const map = new Map();
const objKey = { id: 1 };map.set(objKey, 'value');
console.log(map.get(objKey));
console.log(map.has(objKey));
🔢 Set:值的集合(无重复元素)
特点
- 值唯一,无重复
- 任意类型都可以存储
- 类似于数组但去重、查找更快
常用方法
方法 | 描述 |
---|
add(value) | 添加元素 |
has(value) | 是否存在该元素 |
delete(value) | 删除元素 |
clear() | 清空集合 |
size | 当前元素个数 |
示例
const set = new Set([1, 2, 2, 3]);
console.log(set);
set.add(4);
set.has(2);
🧩 WeakMap:弱引用键值对集合(key 只能是对象)
特点
- key 必须是对象(不能是字符串、数字等)
- 键是弱引用(不会阻止垃圾回收)
- 无法遍历(没有 .keys()、.entries() 等)
- 用于私有数据存储或DOM 元素绑定数据
常用方法
方法 | 描述 |
---|
set(obj, value) | 添加键值对 |
get(obj) | 获取值 |
has(obj) | 是否存在该键 |
delete(obj) | 删除键值对 |
示例
const wm = new WeakMap();
let obj = { name: 'temp' };wm.set(obj, 'some data');
console.log(wm.get(obj)); obj = null;
🔑 WeakSet:弱引用值的集合(value 只能是对象)
特点
- 只能存储对象
- 弱引用:对象被 GC 后自动移除
- 不能遍历
常用方法
方法 | 描述 |
---|
add(obj) | 添加对象 |
has(obj) | 是否存在 |
delete(obj) | 删除对象 |
示例
const ws = new WeakSet();
let obj = { id: 1 };ws.add(obj);
console.log(ws.has(obj)); obj = null;
🔍 四者对比总结
特性 | Map | Set | WeakMap | WeakSet |
---|
存储结构 | key → value | value | object → value | object |
键是否可为对象 | ✅ | ✅ | ✅(必须) | ✅(必须) |
键是否为弱引用 | ❌ | ❌ | ✅ | ✅ |
是否可遍历 | ✅ | ✅ | ❌ | ❌ |
可用于缓存 / 私有存储 | ✅(有限) | ❌ | ✅(强烈推荐) | ✅(适用) |