当前位置: 首页 > news >正文

JavaScript数据结构

目录

JavaScript数据结构

一、基础数据结构

1. 数组(Array)

2. 对象(Object)

二、ES6+ 高级数据结构

1. Map

2. Set

3. WeakMap 与 WeakSet

三、类型化数组(Typed Arrays)

四、其他数据结构实现

1. 栈(Stack)

2. 队列(Queue)

3. 链表(Linked List)

五、数据结构选择指南

六、最佳实践

JavaScript中的for循环

1. 传统 for 循环

语法

示例

特点

2. for...of 循环

语法

示例

特点

3. for...in 循环

语法

示例

特点

4. Array.prototype.forEach

语法

示例

特点

5. 性能与选择指南

性能对比

如何选择?

6. 常见陷阱

1. 修改数组长度

2. 闭包问题

3. 遍历稀疏数组


JavaScript数据结构


一、基础数据结构

1. 数组(Array)

  • 定义:有序元素集合,可存储任意类型值。

  • 创建方式

    let arr1 = [1, "a", true];      // 字面量
    let arr2 = new Array(3);        // 创建长度3的空数组(慎用)
  • 核心方法

    • 增删元素

      arr.push(4);        // 末尾添加 → [1, 2, 3, 4]
      arr.pop();          // 移除末尾 → [1, 2]
      arr.unshift(0);     // 开头添加 → [0, 1, 2]
      arr.shift();        // 移除开头 → [1, 2]
    • 操作数组

      arr.splice(1, 1, "x");  // 从索引1删除1个元素,插入"x" → [1, "x", 3]
      arr.slice(1, 3);         // 截取索引1到3(不包含3)→ ["x", 3]
      arr.concat([4, 5]);      // 合并数组 → [1, 2, 3, 4, 5]
    • 迭代与转换

      arr.map(x => x * 2);     // 映射新数组 → [2, 4, 6]
      arr.filter(x => x > 1);  // 过滤 → [2, 3]
      arr.reduce((sum, x) => sum + x, 0); // 累加 → 6
  • 注意事项

    • 稀疏数组:空位(如 new Array(3))可能引发意外行为。

    • 引用类型:数组赋值传递引用,需用 [...arr] 或 arr.slice() 克隆。


2. 对象(Object)

  • 定义:键值对集合,键为字符串或 Symbol。

  • 创建方式

    let obj1 = { name: "Alice", age: 25 }; // 字面量
    let obj2 = new Object();               // 构造函数
  • 核心操作

    • 增删查改

      obj.email = "alice@example.com"; // 添加属性
      delete obj.age;                  // 删除属性
      console.log("name" in obj);      // 检查属性是否存在 → true
    • 遍历

      Object.keys(obj);    // 返回键数组 → ["name", "email"]
      Object.values(obj);  // 返回值数组 → ["Alice", "alice@example.com"]
      for (let key in obj) { console.log(key, obj[key]); } // 遍历自身及原型链属性
  • 注意事项

    • 原型污染:避免修改 Object.prototype

    • 键顺序:ES6 后字符串键按插入顺序保留,但数字键优先排序。


二、ES6+ 高级数据结构

1. Map

  • 特点

    • 键可以是任意类型(对象、函数等)。

    • 保持插入顺序。

  • 核心方法

    let map = new Map();
    map.set("key", "value");    // 添加键值对
    map.get("key");             // 获取值 → "value"
    map.has("key");             // 检查存在 → true
    map.delete("key");          // 删除键值对
    map.size;                   // 获取条目数
  • 适用场景:需要复杂键或频繁增删键值对时,优于 Object。


2. Set

  • 特点:存储唯一值,自动去重。

  • 核心方法

    let set = new Set();
    set.add(1);                 // 添加值
    set.add(2);
    set.has(1);                 // 检查存在 → true
    set.delete(1);              // 删除值
    set.size;                   // 获取元素数量
  • 适用场景:去重、集合运算(并集、交集等)。


3. WeakMap 与 WeakSet

  • 特点

    • 弱引用:键必须是对象,不阻止垃圾回收。

    • 不可迭代:无 sizeclear() 或遍历方法。

  • 使用场景

    • WeakMap:存储对象关联的私有数据或元数据。

      let wm = new WeakMap();
      let obj = {};
      wm.set(obj, "secret");
    • WeakSet:标记对象(如跟踪已处理对象)。

      let ws = new WeakSet();
      ws.add(obj);

三、类型化数组(Typed Arrays)

用于处理二进制数据(如图像、音频),与 ArrayBuffer 配合使用。

  • 常见类型

    • Int8ArrayUint8Array(8位整数)

    • Int16ArrayFloat32Array 等。

  • 示例

    let buffer = new ArrayBuffer(16);      // 分配16字节内存
    let int32View = new Int32Array(buffer); // 32位整数视图(4个元素)
    int32View[0] = 42;

四、其他数据结构实现

JavaScript 未内置,但可通过基础结构模拟:

1. 栈(Stack)

  • 后进先出(LIFO),用数组实现:

    class Stack {
      constructor() { this.items = []; }
      push(element) { this.items.push(element); }
      pop() { return this.items.pop(); }
      peek() { return this.items[this.items.length - 1]; }
    }

2. 队列(Queue)

  • 先进先出(FIFO)

    class Queue {
      constructor() { this.items = []; }
      enqueue(element) { this.items.push(element); }
      dequeue() { return this.items.shift(); } // 时间复杂度 O(n)
    }

3. 链表(Linked List)

  • 节点链接实现

    class Node {
      constructor(value) {
        this.value = value;
        this.next = null;
      }
    }
    class LinkedList {
      constructor() { this.head = null; }
      append(value) { /* 实现添加逻辑 */ }
    }

五、数据结构选择指南

场景推荐数据结构理由
有序集合,需快速访问索引数组(Array)索引操作时间复杂度 O(1)
键值对,键为字符串或 Symbol对象(Object)语法简洁,查找速度快
键为任意类型,需维护插入顺序Map支持复杂键,有序
存储唯一值Set自动去重,集合运算高效
高频增删元素(如队列)链表(自定义实现)避免数组 shift() 的 O(n) 复杂度
二进制数据处理类型化数组(Typed Array)内存高效,适合底层操作

六、最佳实践

  1. 优先使用 ES6+ 数据结构:如 MapSet 替代传统对象和数组,提升代码可读性。

  2. 注意引用类型副作用:克隆数据避免意外修改。

  3. 性能敏感场景优化:如用 Int32Array 替代普通数组处理大量数值。

  4. 垃圾回收考虑:使用 WeakMap/WeakSet 管理对象关联数据,防止内存泄漏。


  

JavaScript中的for循环


1. 传统 for 循环

最基础的循环结构,通过明确的初始化条件迭代器控制循环。

语法

for (初始化; 条件; 迭代器) {
  // 循环体
}

示例

// 遍历数组
const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]); // 输出 1, 2, 3
}

// 倒序循环
for (let i = arr.length - 1; i >= 0; i--) {
  console.log(arr[i]); // 输出 3, 2, 1
}

特点

  • 灵活控制:可自定义步长(如 i += 2)、跳过某次循环(continue)或提前退出(break)。

  • 性能优化:预存数组长度(如 let len = arr.length)避免重复计算。

  • 作用域:使用 let 声明变量时,每次循环会创建新的块级作用域。


2. for...of 循环

遍历可迭代对象(如数组、字符串、Map、Set、生成器等)的值。

语法

for (const value of iterable) {
  // 使用 value
}

示例

const arr = ['a', 'b', 'c'];
for (const val of arr) {
  console.log(val); // 输出 'a', 'b', 'c'
}

// 遍历字符串
for (const char of 'Hello') {
  console.log(char); // 输出 H, e, l, l, o
}

特点

  • 简洁性:无需索引,直接获取值。

  • 支持异步:可与 await 结合使用(需在 async 函数中)。

  • 不适用于普通对象:默认对象不可迭代(除非自行实现 Symbol.iterator)。


3. for...in 循环

遍历对象的可枚举属性(包括原型链上的属性)。

语法

for (const key in object) {
  // 使用 key 访问属性值:object[key]
}

示例

const obj = { a: 1, b: 2 };
for (const key in obj) {
  console.log(key, obj[key]); // 输出 a 1, b 2
}

// 遍历数组(不推荐!)
const arr = [1, 2, 3];
arr.foo = 'bar';
for (const key in arr) {
  console.log(key); // 输出 0, 1, 2, 'foo'
}

特点

  • 遍历对象属性:适合处理键值对。

  • 可能遍历原型链:需用 hasOwnProperty 过滤:

    for (const key in obj) {
      if (obj.hasOwnProperty(key)) {
        // 仅处理自身属性
      }
    }
  • 不保证顺序:现代引擎通常按属性添加顺序遍历,但复杂场景可能不一致。


4. Array.prototype.forEach

数组专用的高阶函数,遍历每个元素。

语法

array.forEach((value, index, array) => {
  // 循环体
});

示例

const arr = [1, 2, 3];
arr.forEach((value, index) => {
  console.log(index, value); // 输出 0 1, 1 2, 2 3
});

特点

  • 不可中断:无法使用 break 或 continue,需通过 return 跳过当前迭代。

  • 链式调用:可与其他数组方法(如 mapfilter)配合。

  • 异步陷阱:回调函数中的 await 不会暂停外层循环。


5. 性能与选择指南

性能对比

  • 最快:传统 for 循环(尤其预存长度时)。

  • 适中for...of(底层使用迭代器协议)。

  • 较慢forEach(函数调用开销)。

如何选择?

场景推荐方式
需要索引或复杂控制传统 for 循环
遍历数组值(无需索引)for...of
遍历对象属性for...in + 过滤
简单数组操作forEach
处理稀疏数组传统 for + 判空

6. 常见陷阱

1. 修改数组长度

const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
  arr.pop(); // 可能导致无限循环或跳过元素
}

2. 闭包问题

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i)); // 输出 3, 3, 3
}
// 解决:改用 let 或 IIFE

3. 遍历稀疏数组

const arr = [1, , 3]; // 中间是空位
arr.forEach(v => console.log(v)); // 输出 1, 3(跳过空位)
for (const v of arr) console.log(v); // 输出 1, undefined, 3

相关文章:

  • vue3大屏适配
  • Java使用Californium 实现CoAP协议交互代码案例
  • springboot3 基于 logback
  • Python第七章02:文件读取的练习
  • Qt 多线程的两种实现方式
  • 表单对象与当前行对象的 区别
  • 基于Spring的forum系统测试报告
  • MYSQL中对行与列的操作
  • 【leetcode刷题日记】lc.238-除自身以外数组的乘积
  • redis 缓存命中率降低,该如何解决?
  • OMNIWeb 数据介绍
  • uniapp用法--uni.navigateTo 使用与参数携带的方式示例(包含复杂类型参数)
  • 合合信息大模型加速器2.0实测:当AI开始“读心术“与“考古“
  • 若依框架二次开发——若依(RuoYi)实现手机号/邮箱/用户名多方式登录
  • 【MySQL基础-18】MySQL字符函数详解:高效处理文本数据的利器
  • 说说Redis的内存淘汰策略?
  • 课程6. 决策树
  • #不同版本下,单元测试的注解使用
  • Mysql从入门到精通day5————子查询精讲
  • 人工智能的未来:从弱 AI 到通用人工智能(AGI)
  • html页面能做成网站吗/百度快照优化的优势是什么
  • 商务网站建设实训/青岛官网优化
  • 营销策略都有哪些4p/seo网络培训学校
  • 建设银行天津分行门户网站/南宁seo服务优化
  • 做调查问卷权威网站/seo链接优化建议
  • 网络专业的网站建设价格/百度搜索如何去广告