JavaScript:10个数组方法/属性

发布于:2025-07-30 ⋅ 阅读:(26) ⋅ 点赞:(0)

1. length (属性)

深度解析:
  • 技术原理:动态反映数组当前元素数量,基于最大索引值+1

  • 特殊行为

    • 设置小于当前长度:截断数组(不可逆操作)

    • 设置大于当前长度:创建空位(empty slots),访问返回undefined但迭代跳过

    • 空位与undefined的区别:[,1] vs [undefined,1]

 

使用场景:
1.快速清空数组(性能最优):
const data = [/* 大量数据 */];
data.length = 0; // 比 data = [] 更高效
2.数组截断
const logs = ['log1', 'log2', 'log3', 'log4'];
// 只保留最后2条日志
logs.length = Math.min(logs.length, 2);
3.预分配大数组(谨慎使用):
const pixelData = new Array(1920*1080); // 创建200万空位
// 后续填充数据(比动态push高效)
注意事项:
// 空位陷阱示例
const sparseArr = [1, , 3];
console.log(sparseArr.length); // 3
console.log(sparseArr[1]);     // undefined

// forEach跳过空位
sparseArr.forEach(v => console.log(v)); // 只输出1和3

// 解决:显式填充undefined
const denseArr = Array.from(sparseArr); // [1, undefined, 3]

2. push()

深度解析:
  • 技术原理:修改原数组,在末尾添加元素,返回新长度

  • 性能特点:O(1)时间复杂度(摊销常数时间)

 使用场景:
1.动态数据收集
const userInputs = [];
inputElement.addEventListener('change', (e) => {
  userInputs.push(e.target.value);
});
 2.栈操作(LIFO)
const historyStack = [];
function doAction(action) {
  historyStack.push(action);
  // 执行操作...
}
3.批量添加元素
// 优于多次调用push
const newItems = ['item4', 'item5', 'item6'];
items.push(...newItems); // 扩展运算符
最佳实践:
// 避免在循环中连续push
// 反例(性能差):
for(let i=0; i<10000; i++) {
  arr.push(i);
}

// 正例(预分配):
const arr = new Array(10000);
for(let i=0; i<10000; i++) {
  arr[i] = i;
}

3. pop()

深度解析:
  • 技术原理:移除最后一个元素并返回,修改原数组长度

  • 边界情况:空数组调用返回undefined

使用场景:
1.栈操作(LIFO)
function undo() {
  if(historyStack.length > 0) {
    const lastAction = historyStack.pop();
    revertAction(lastAction);
  }
}
2.处理任务队列
while(taskQueue.length > 0) {
  const task = taskQueue.pop();
  executeTask(task);
}
3.递归处理嵌套结构
function flatten(arr) {
  const result = [];
  while(arr.length) {
    const next = arr.pop();
    if(Array.isArray(next)) {
      arr.push(...next);
    } else {
      result.push(next);
    }
  }
  return result.reverse();
}
注意事项:
// 不可逆操作警告
const original = [1, 2, 3];
const last = original.pop(); 
console.log(original); // [1,2] - 永久改变

4. shift()

深度解析:
  • 技术原理:移除首元素并返回,所有后续元素前移

  • 性能问题:O(n)时间复杂度,大数据量慎用

 

使用场景:
1.队列处理(FIFO)
const messageQueue = [];

// 入队
socket.on('message', msg => messageQueue.push(msg));

// 处理队列
setInterval(() => {
  if(messageQueue.length > 0) {
    processMessage(messageQueue.shift());
  }
}, 100);
2.流式数据处理
while(dataStream.length) {
  const packet = dataStream.shift();
  parsePacket(packet);
}
性能优化:
// 替代方案:使用索引指针
class Queue {
  constructor() {
    this.items = {};
    this.front = 0;
    this.rear = 0;
  }
  
  enqueue(item) {
    this.items[this.rear++] = item;
  }
  
  dequeue() {
    if(this.front >= this.rear) return null;
    const item = this.items[this.front];
    delete this.items[this.front++];
    return item;
  }
}

5. unshift()

深度解析:
  • 技术原理:在数组开头添加元素,所有现有元素后移

  • 性能问题:O(n)时间复杂度,大数据量避免使用

使用场景:
1.优先级队列: 
const tasks = [];

function addTask(task, isHighPriority) {
  if(isHighPriority) {
    tasks.unshift(task); // 高优先级插队
  } else {
    tasks.push(task);
  }
}
2.时间线展示(最新在前)
const timeline = [];

function addEvent(event) {
  timeline.unshift(event); // 新事件在开头
  if(timeline.length > 100) timeline.pop(); // 限制长度
}
替代方案:
// 使用reverse + push 替代
const arr = [3,4];
arr.reverse().push(1,2);
arr.reverse(); // [1,2,3,4]

// 大数据量使用链表
class LinkedList {
  // 实现链表结构...
}

6. forEach()

深度解析:
  • 技术原理:为每个元素执行回调(元素,索引,原数组)

  • 重要特性

    • 无法用break中断

    • 空位会被跳过

    • 不等待异步操作

使用场景:
1.DOM批量操作
const buttons = document.querySelectorAll('button');
buttons.forEach(btn => {
  btn.addEventListener('click', handleClick);
});
2.执行副作用操作
const users = [/*...*/];
users.forEach(user => {
  saveToLocalStorage(user.id, user);
});
异步处理:
// 错误:不会等待
items.forEach(async item => {
  await processItem(item); // 不会顺序执行
});

// 正确:使用for...of
async function processAll() {
  for(const item of items) {
    await processItem(item);
  }
}

7. map()

深度解析:
  • 技术原理:创建新数组,每个元素是回调返回值

  • 核心特性

    • 不修改原数组(纯函数)

    • 保持数组长度不变

    • 跳过空位

使用场景:
1.数据格式转换
const apiResponse = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

const userIds = apiResponse.map(user => user.id); // [1,2]
2.JSX列表渲染
function UserList({ users }) {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}
3.数学计算
const temperaturesC = [0, 25, 100];
const temperaturesF = temperaturesC.map(c => c * 9/5 + 32);
最佳实践:
// 避免在map中产生副作用
// 反例:
items.map(item => {
  saveItem(item); // 副作用操作
  return item.id;
});

// 正例:使用forEach处理副作用
const ids = [];
items.forEach(item => {
  saveItem(item);
  ids.push(item.id);
});

8. filter()

深度解析:
  • 技术原理:返回回调返回truthy的元素组成的新数组

  • 重要特性

    • 不修改原数组

    • 结果数组长度 <= 原数组

    • 跳过空位

使用场景: 
1.数据筛选
const products = [/*...*/];
const availableProducts = products.filter(p => p.stock > 0);
2.搜索功能
function search(query) {
  return items.filter(item => 
    item.name.toLowerCase().includes(query.toLowerCase())
  );
}
3.数据清理
const userInput = ['', 'valid', null, 'data'];
const validInput = userInput.filter(Boolean); // ['valid','data']
高级用法:
// 链式调用
const result = data
  .filter(item => item.category === 'electronics')
  .filter(item => item.price < 100)
  .map(item => item.name);

// 结合索引去重
const unique = array.filter((item, index) => 
  array.indexOf(item) === index
);

9. find()

深度解析:
  • 技术原理:返回第一个使回调返回truthy的元素

  • 重要特性

    • 找到即停止遍历

    • 未找到返回undefined

    • filter()[0]更高效

使用场景: 
1.ID查找: 
const users = [/*...*/];
function findUser(id) {
  return users.find(user => user.id === id);
}
2.条件查找
const inventory = [
  { name: 'apple', color: 'red' },
  { name: 'banana', color: 'yellow' }
];

const yellowFruit = inventory.find(f => f.color === 'yellow');
3.配置查找
const configOptions = [
  { env: 'dev', apiUrl: 'dev.api.com' },
  { env: 'prod', apiUrl: 'api.com' }
];

const currentConfig = configOptions.find(c => 
  c.env === process.env.NODE_ENV
);
findIndex配合:
const index = users.findIndex(user => user.id === 123);
if(index !== -1) {
  // 更新用户
  users[index] = updatedUser;
}

10. includes()

深度解析:
  • 技术原理:使用SameValueZero算法检查包含性

  • 关键特性

    • NaN可以匹配NaN

    • 区分+0和-0

    • 对象比较引用而非内容

使用场景: 
1.简单值存在检查
const validStatuses = ['active', 'pending', 'completed'];

function isValidStatus(status) {
  return validStatuses.includes(status);
}
2.功能开关控制
const enabledFeatures = getUserFeatures();

if(enabledFeatures.includes('dark_mode')) {
  enableDarkMode();
}
 3.白名单验证
const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/png'];

function isValidFile(file) {
  return ALLOWED_FILE_TYPES.includes(file.type);
}
对象数组处理:
// 无法直接查找对象
const items = [{id:1}, {id:2}];
console.log(items.includes({id:1})); // false

// 解决方案:
const target = {id:1};
const itemSet = new Set(items.map(i => i.id));
console.log(itemSet.has(1)); // true

// 或使用some
const exists = items.some(item => item.id === 1);

专业级总结:选择指南

场景 推荐方法 原因
遍历数组 for...of 或 forEach 简洁性 vs 可中断性
数据转换 map 纯函数,无副作用
数据筛选 filter 声明式编程
查找元素 find / findIndex 高效(短路特性)
存在检查 includes (简单值) / some (复杂) 语义化清晰
添加元素 push (尾) / unshift (头,慎用) 性能考虑
移除元素 pop (尾) / shift (头,慎用) 性能考虑
清空数组 arr.length = 0 最高性能
异步遍历 for...of + await 顺序执行
复杂数据操作 reduce (未列出) 灵活处理累积操作

高级建议

1.不可变性原则:优先使用mapfilterslice等非变异方法
2.性能敏感操作
// 大数组操作使用TypedArray
const buffer = new Float64Array(1000000);

// 替代shift/unshift
class CircularBuffer {
  // 实现循环缓冲区
}
3.函数式编程组合
import { pipe } from 'lodash/fp';

const processData = pipe(
  filter(validCondition),
  map(transform),
  sort(comparator)
);

const result = processData(rawData);


网站公告

今日签到

点亮在社区的每一天
去签到