数组基础

数组创建和基本操作

// 数组创建方式
// 1. 数组字面量(推荐)
const fruits = ['apple', 'banana', 'orange'];
const numbers = [1, 2, 3, 4, 5];
const mixed = [1, 'hello', true, null, { name: 'object' }];

// 2. Array构造函数
const arr1 = new Array();           // 空数组
const arr2 = new Array(5);          // 长度为5的空数组
const arr3 = new Array(1, 2, 3);    // [1, 2, 3]

// 3. Array.of()(避免构造函数的歧义)
const arr4 = Array.of(5);           // [5]
const arr5 = Array.of(1, 2, 3);     // [1, 2, 3]

// 4. Array.from()(从类数组或可迭代对象创建)
const str = 'hello';
const arrFromString = Array.from(str); // ['h', 'e', 'l', 'l', 'o']

const nodeList = document.querySelectorAll('div'); // 假设的NodeList
const arrFromNodeList = Array.from(nodeList);

// 使用映射函数
const arrWithMap = Array.from([1, 2, 3], x => x * 2); // [2, 4, 6]

// 基本属性和方法
console.log(fruits.length);         // 3
console.log(fruits[0]);             // 'apple'
console.log(fruits[fruits.length - 1]); // 'orange'

// 修改数组
fruits[1] = 'grape';                // 替换元素
fruits[fruits.length] = 'kiwi';     // 添加到末尾
fruits[10] = 'mango';               // 创建稀疏数组

console.log(fruits.length);         // 11
console.log(fruits[5]);             // undefined

// 检查是否为数组
console.log(Array.isArray(fruits)); // true
console.log(Array.isArray('hello')); // false

// 数组转换
const arrToString = fruits.toString();     // 'apple,grape,orange,kiwi,,,,,,,mango'
const arrToJoin = fruits.join(' | ');      // 'apple | grape | orange | kiwi | | | | | | | mango'
const arrToJSON = JSON.stringify(fruits);  // JSON字符串

数组添加和删除元素

const animals = ['cat', 'dog'];

// 末尾操作
animals.push('bird');               // 添加到末尾,返回新长度
animals.push('fish', 'rabbit');     // 添加多个元素
console.log(animals);               // ['cat', 'dog', 'bird', 'fish', 'rabbit']

const lastAnimal = animals.pop();   // 删除并返回最后一个元素
console.log(lastAnimal);            // 'rabbit'
console.log(animals);               // ['cat', 'dog', 'bird', 'fish']

// 开头操作
animals.unshift('lion');            // 添加到开头,返回新长度
animals.unshift('tiger', 'bear');   // 添加多个元素
console.log(animals);               // ['tiger', 'bear', 'lion', 'cat', 'dog', 'bird', 'fish']

const firstAnimal = animals.shift(); // 删除并返回第一个元素
console.log(firstAnimal);           // 'tiger'
console.log(animals);               // ['bear', 'lion', 'cat', 'dog', 'bird', 'fish']

// splice方法(最灵活的数组修改方法)
const colors = ['red', 'green', 'blue', 'yellow', 'purple'];

// 删除元素
const removed = colors.splice(1, 2); // 从索引1开始删除2个元素
console.log(removed);               // ['green', 'blue']
console.log(colors);                // ['red', 'yellow', 'purple']

// 插入元素
colors.splice(1, 0, 'orange', 'pink'); // 在索引1插入元素,不删除
console.log(colors);                // ['red', 'orange', 'pink', 'yellow', 'purple']

// 替换元素
colors.splice(2, 1, 'cyan');        // 删除索引2的1个元素,插入'cyan'
console.log(colors);                // ['red', 'orange', 'cyan', 'yellow', 'purple']

// 清空数组的方法
const temp = [1, 2, 3, 4, 5];

// 方法1:设置length为0
temp.length = 0;
console.log(temp);                  // []

// 方法2:splice
const temp2 = [1, 2, 3, 4, 5];
temp2.splice(0);
console.log(temp2);                 // []

// 方法3:重新赋值(如果有其他引用,不会影响其他引用)
let temp3 = [1, 2, 3, 4, 5];
temp3 = [];

数组查找和检测

const numbers = [1, 2, 3, 4, 5, 3, 6, 7, 3];
const users = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 },
  { id: 3, name: 'Charlie', age: 35 },
  { id: 4, name: 'David', age: 25 }
];

// indexOf和lastIndexOf
console.log(numbers.indexOf(3));        // 2(第一次出现的索引)
console.log(numbers.lastIndexOf(3));    // 8(最后一次出现的索引)
console.log(numbers.indexOf(10));       // -1(不存在)

// includes(ES2016)
console.log(numbers.includes(5));       // true
console.log(numbers.includes(10));      // false

// find和findIndex(ES2015)
const foundUser = users.find(user => user.age === 25);
console.log(foundUser);                 // { id: 1, name: 'Alice', age: 25 }

const foundIndex = users.findIndex(user => user.name === 'Charlie');
console.log(foundIndex);                // 2

const notFound = users.find(user => user.age === 100);
console.log(notFound);                  // undefined

// some和every
const hasAdult = users.some(user => user.age >= 18);
console.log(hasAdult);                  // true

const allAdults = users.every(user => user.age >= 18);
console.log(allAdults);                 // true

const allYoung = users.every(user => user.age < 30);
console.log(allYoung);                  // false

// 自定义查找函数
function findAll(arr, predicate) {
  const result = [];
  for (let i = 0; i < arr.length; i++) {
    if (predicate(arr[i], i, arr)) {
      result.push(arr[i]);
    }
  }
  return result;
}

const youngUsers = findAll(users, user => user.age < 30);
console.log(youngUsers);                // Alice和Bob

// 查找最大值和最小值
const scores = [85, 92, 78, 96, 88];

const maxScore = Math.max(...scores);
const minScore = Math.min(...scores);
console.log(`Max: ${maxScore}, Min: ${minScore}`); // Max: 96, Min: 78

// 使用reduce查找
const maxUser = users.reduce((max, user) => 
  user.age > max.age ? user : max
);
console.log('Oldest user:', maxUser);   // Charlie

// 二分查找(适用于已排序数组)
function binarySearch(arr, target) {
  let left = 0;
  let right = arr.length - 1;
  
  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    
    if (arr[mid] === target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  
  return -1;
}

const sortedNumbers = [1, 3, 5, 7, 9, 11, 13, 15];
console.log(binarySearch(sortedNumbers, 7));  // 3
console.log(binarySearch(sortedNumbers, 6));  // -1

数组高阶方法

map、filter、reduce

const numbers = [1, 2, 3, 4, 5];
const products = [
  { id: 1, name: 'Laptop', price: 999, category: 'Electronics' },
  { id: 2, name: 'Phone', price: 599, category: 'Electronics' },
  { id: 3, name: 'Book', price: 29, category: 'Education' },
  { id: 4, name: 'Headphones', price: 199, category: 'Electronics' },
  { id: 5, name: 'Notebook', price: 5, category: 'Education' }
];

// map - 转换数组元素
const doubled = numbers.map(num => num * 2);
console.log(doubled);                   // [2, 4, 6, 8, 10]

const productNames = products.map(product => product.name);
console.log(productNames);              // ['Laptop', 'Phone', 'Book', 'Headphones', 'Notebook']

// 带索引的map
const withIndex = numbers.map((num, index) => `${index}: ${num}`);
console.log(withIndex);                 // ['0: 1', '1: 2', '2: 3', '3: 4', '4: 5']

// 复杂转换
const productSummary = products.map(product => ({
  id: product.id,
  displayName: `${product.name} - $${product.price}`,
  isExpensive: product.price > 100
}));
console.log(productSummary);

// filter - 过滤数组元素
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers);               // [2, 4]

const expensiveProducts = products.filter(product => product.price > 100);
console.log(expensiveProducts);         // Laptop, Phone, Headphones

const electronics = products.filter(product => product.category === 'Electronics');
console.log(electronics);

// 复杂过滤
const affordableElectronics = products.filter(product => 
  product.category === 'Electronics' && product.price < 600
);
console.log(affordableElectronics);     // Phone, Headphones

// reduce - 累积计算
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum);                       // 15

const product = numbers.reduce((acc, num) => acc * num, 1);
console.log(product);                   // 120

// 计算总价
const totalPrice = products.reduce((total, product) => total + product.price, 0);
console.log(totalPrice);                // 1831

// 按类别分组
const groupedByCategory = products.reduce((groups, product) => {
  const category = product.category;
  if (!groups[category]) {
    groups[category] = [];
  }
  groups[category].push(product);
  return groups;
}, {});
console.log(groupedByCategory);

// 找到最贵的产品
const mostExpensive = products.reduce((max, product) => 
  product.price > max.price ? product : max
);
console.log(mostExpensive);             // Laptop

// 计算平均价格
const averagePrice = products.reduce((sum, product, index, array) => {
  sum += product.price;
  return index === array.length - 1 ? sum / array.length : sum;
}, 0);
console.log(averagePrice);              // 366.2

// reduceRight - 从右到左累积
const letters = ['a', 'b', 'c', 'd'];
const rightToLeft = letters.reduceRight((acc, letter) => acc + letter, '');
console.log(rightToLeft);               // 'dcba'

// 链式调用
const result = products
  .filter(product => product.category === 'Electronics')
  .map(product => ({ ...product, discountPrice: product.price * 0.9 }))
  .reduce((total, product) => total + product.discountPrice, 0);

console.log('Total discounted price:', result);

forEach和其他迭代方法

const fruits = ['apple', 'banana', 'orange', 'grape'];
const numbers = [1, 2, 3, 4, 5];

// forEach - 遍历数组
fruits.forEach((fruit, index) => {
  console.log(`${index}: ${fruit}`);
});

// forEach不能使用break或continue
// 如需提前退出,使用for循环或some/every
fruits.forEach((fruit, index) => {
  if (fruit === 'banana') {
    return; // 相当于continue,跳过当前迭代
  }
  console.log(fruit);
});

// 修改原数组(注意:不推荐在forEach中修改数组结构)
const mutableNumbers = [1, 2, 3, 4, 5];
mutableNumbers.forEach((num, index, arr) => {
  arr[index] = num * 2;
});
console.log(mutableNumbers);            // [2, 4, 6, 8, 10]

// entries() - 返回键值对迭代器
for (const [index, fruit] of fruits.entries()) {
  console.log(`${index}: ${fruit}`);
}

// keys() - 返回索引迭代器
for (const index of fruits.keys()) {
  console.log(`Index: ${index}`);
}

// values() - 返回值迭代器
for (const fruit of fruits.values()) {
  console.log(`Fruit: ${fruit}`);
}

// 使用解构和迭代器
const [[firstIndex, firstFruit], [secondIndex, secondFruit]] = fruits.entries();
console.log(`First: ${firstIndex}-${firstFruit}, Second: ${secondIndex}-${secondFruit}`);

// 自定义迭代器
function* arrayIterator(arr) {
  for (let i = 0; i < arr.length; i++) {
    yield { index: i, value: arr[i], isLast: i === arr.length - 1 };
  }
}

for (const item of arrayIterator(fruits)) {
  console.log(item);
}

// 异步forEach(注意:forEach不等待异步操作)
const asyncNumbers = [1, 2, 3];

// 错误的异步处理
console.log('Start');
asyncNumbers.forEach(async (num) => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log(num);
});
console.log('End'); // 这会在数字打印之前执行

// 正确的异步处理
async function processArraySequentially(arr, asyncFn) {
  for (const item of arr) {
    await asyncFn(item);
  }
}

async function processArrayConcurrently(arr, asyncFn) {
  await Promise.all(arr.map(asyncFn));
}

// 使用示例
async function delayedLog(num) {
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log(num);
}

// 顺序执行
processArraySequentially(asyncNumbers, delayedLog);

// 并发执行
processArrayConcurrently(asyncNumbers, delayedLog);

数组排序和反转

const numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5];
const fruits = ['banana', 'apple', 'orange', 'grape'];
const people = [
  { name: 'Alice', age: 25, salary: 50000 },
  { name: 'Bob', age: 30, salary: 60000 },
  { name: 'Charlie', age: 35, salary: 55000 },
  { name: 'David', age: 25, salary: 45000 }
];

// 基本排序(修改原数组)
const sortedNumbers = [...numbers].sort(); // 创建副本再排序
console.log(sortedNumbers);             // ['1', '1', '2', '3', '4', '5', '5', '6', '9'] (字符串排序)

// 数字排序
const numericSort = [...numbers].sort((a, b) => a - b);
console.log(numericSort);               // [1, 1, 2, 3, 4, 5, 5, 6, 9]

const reverseNumericSort = [...numbers].sort((a, b) => b - a);
console.log(reverseNumericSort);        // [9, 6, 5, 5, 4, 3, 2, 1, 1]

// 字符串排序
const sortedFruits = [...fruits].sort();
console.log(sortedFruits);              // ['apple', 'banana', 'grape', 'orange']

// 忽略大小写排序
const mixedCase = ['Banana', 'apple', 'Orange', 'grape'];
const caseInsensitiveSort = [...mixedCase].sort((a, b) => 
  a.toLowerCase().localeCompare(b.toLowerCase())
);
console.log(caseInsensitiveSort);       // ['apple', 'Banana', 'grape', 'Orange']

// 对象排序
// 按年龄排序
const sortedByAge = [...people].sort((a, b) => a.age - b.age);
console.log(sortedByAge);

// 按姓名排序
const sortedByName = [...people].sort((a, b) => a.name.localeCompare(b.name));
console.log(sortedByName);

// 多条件排序
const multiSort = [...people].sort((a, b) => {
  // 首先按年龄排序
  if (a.age !== b.age) {
    return a.age - b.age;
  }
  // 年龄相同时按薪资排序
  return b.salary - a.salary;
});
console.log(multiSort);

// 自定义排序函数
function sortBy(arr, ...criteria) {
  return [...arr].sort((a, b) => {
    for (const criterion of criteria) {
      let result;
      
      if (typeof criterion === 'string') {
        // 按属性名排序
        result = a[criterion] > b[criterion] ? 1 : a[criterion] < b[criterion] ? -1 : 0;
      } else if (typeof criterion === 'function') {
        // 按函数结果排序
        result = criterion(a, b);
      } else if (criterion.key) {
        // 按配置对象排序
        const aVal = criterion.key(a);
        const bVal = criterion.key(b);
        result = aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
        if (criterion.reverse) result *= -1;
      }
      
      if (result !== 0) return result;
    }
    return 0;
  });
}

// 使用自定义排序
const customSorted = sortBy(
  people,
  { key: person => person.age, reverse: false },
  { key: person => person.salary, reverse: true }
);
console.log(customSorted);

// 反转数组
const reversed = [...numbers].reverse();
console.log(reversed);                  // [5, 6, 2, 9, 5, 1, 4, 1, 3]

// 洗牌算法(Fisher-Yates)
function shuffle(arr) {
  const shuffled = [...arr];
  for (let i = shuffled.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
  }
  return shuffled;
}

const shuffledNumbers = shuffle(numbers);
console.log(shuffledNumbers);

// 稳定排序检查
const items = [
  { name: 'A', value: 1 },
  { name: 'B', value: 2 },
  { name: 'C', value: 1 },
  { name: 'D', value: 2 }
];

const stableSorted = [...items].sort((a, b) => a.value - b.value);
console.log(stableSorted); // 检查相同value的元素是否保持原有顺序

字符串基础

字符串创建和基本操作

// 字符串创建方式
const str1 = 'Hello World';             // 单引号
const str2 = "Hello World";             // 双引号
const str3 = `Hello World`;             // 模板字符串
const str4 = new String('Hello World'); // String构造函数(不推荐)

// 字符串是不可变的
let message = 'Hello';
message[0] = 'h';                       // 无效操作
console.log(message);                   // 仍然是'Hello'

// 字符串属性
console.log(message.length);            // 5

// 字符访问
console.log(message[0]);                // 'H'
console.log(message.charAt(0));         // 'H'
console.log(message.charAt(10));        // ''(超出范围返回空字符串)
console.log(message[10]);               // undefined(超出范围返回undefined)

// 字符编码
console.log(message.charCodeAt(0));     // 72('H'的Unicode编码)
console.log(String.fromCharCode(72));   // 'H'

// Unicode支持
const emoji = '😀🎉🚀';
console.log(emoji.length);              // 6(每个emoji占2个代码单元)
console.log(emoji.charAt(0));           // '😀'的第一部分
console.log([...emoji]);                // ['😀', '🎉', '🚀'](正确分割)

// 使用codePointAt和fromCodePoint处理Unicode
console.log(emoji.codePointAt(0));      // 128512(😀的码点)
console.log(String.fromCodePoint(128512)); // '😀'

// 字符串比较
const a = 'apple';
const b = 'banana';
console.log(a < b);                     // true(字典序比较)
console.log(a.localeCompare(b));        // -1(本地化比较)

// 大小写转换
const text = 'Hello World';
console.log(text.toLowerCase());        // 'hello world'
console.log(text.toUpperCase());        // 'HELLO WORLD'
console.log(text.toLocaleLowerCase());  // 本地化小写
console.log(text.toLocaleUpperCase());  // 本地化大写

// 字符串连接
const firstName = 'John';
const lastName = 'Doe';

// 使用+操作符
const fullName1 = firstName + ' ' + lastName;

// 使用concat方法
const fullName2 = firstName.concat(' ', lastName);

// 使用模板字符串(推荐)
const fullName3 = `${firstName} ${lastName}`;

console.log(fullName1, fullName2, fullName3);

// 重复字符串
const repeated = 'Ha'.repeat(3);        // 'HaHaHa'
console.log(repeated);

// 填充字符串(ES2017)
const num = '42';
console.log(num.padStart(5, '0'));      // '00042'
console.log(num.padEnd(5, '0'));        // '42000'

const time = '9:5:30';
const parts = time.split(':');
const formattedTime = parts.map(part => part.padStart(2, '0')).join(':');
console.log(formattedTime);             // '09:05:30'

字符串查找和提取

const text = 'The quick brown fox jumps over the lazy dog';

// 查找子字符串
console.log(text.indexOf('quick'));     // 4
console.log(text.indexOf('cat'));       // -1(不存在)
console.log(text.lastIndexOf('the'));   // 31(最后一次出现)

// 从指定位置开始查找
console.log(text.indexOf('o', 10));     // 12(从索引10开始查找'o')

// 检查是否包含(ES2015)
console.log(text.includes('fox'));      // true
console.log(text.includes('cat'));      // false

// 检查开头和结尾(ES2015)
console.log(text.startsWith('The'));    // true
console.log(text.startsWith('quick', 4)); // true(从索引4开始检查)
console.log(text.endsWith('dog'));      // true
console.log(text.endsWith('lazy', 40)); // true(在前40个字符中检查结尾)

// 提取子字符串
// substring方法
console.log(text.substring(4, 9));      // 'quick'(不包含结束索引)
console.log(text.substring(9, 4));      // 'quick'(自动交换参数)

// substr方法(已废弃,但仍广泛使用)
console.log(text.substr(4, 5));         // 'quick'(从索引4开始,长度5)

// slice方法(推荐)
console.log(text.slice(4, 9));          // 'quick'
console.log(text.slice(-3));            // 'dog'(从倒数第3个字符开始)
console.log(text.slice(-8, -4));        // 'lazy'(负索引)

// 分割字符串
const words = text.split(' ');
console.log(words);                     // 单词数组

const chars = text.split('');
console.log(chars.length);              // 字符数组长度

// 限制分割数量
const limitedSplit = text.split(' ', 3);
console.log(limitedSplit);              // 只分割前3个单词

// 使用正则表达式分割
const sentence = 'apple,banana;orange:grape';
const fruits = sentence.split(/[,;:]/);
console.log(fruits);                    // ['apple', 'banana', 'orange', 'grape']

// 复杂的字符串解析
function parseCSV(csvString) {
  const lines = csvString.trim().split('\n');
  const headers = lines[0].split(',').map(header => header.trim());
  
  return lines.slice(1).map(line => {
    const values = line.split(',').map(value => value.trim());
    const obj = {};
    headers.forEach((header, index) => {
      obj[header] = values[index];
    });
    return obj;
  });
}

const csvData = `
name, age, city
Alice, 25, New York
Bob, 30, London
Charlie, 35, Paris
`;

const parsedData = parseCSV(csvData);
console.log(parsedData);

// 提取文件名和扩展名
function parseFileName(filePath) {
  const lastSlash = Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\'));
  const fileName = filePath.slice(lastSlash + 1);
  const lastDot = fileName.lastIndexOf('.');
  
  if (lastDot === -1) {
    return { name: fileName, extension: '' };
  }
  
  return {
    name: fileName.slice(0, lastDot),
    extension: fileName.slice(lastDot + 1)
  };
}

console.log(parseFileName('/path/to/document.pdf'));     // { name: 'document', extension: 'pdf' }
console.log(parseFileName('C:\\Users\\file.txt'));      // { name: 'file', extension: 'txt' }
console.log(parseFileName('README'));                   // { name: 'README', extension: '' }

字符串替换和修改

const text = 'The quick brown fox jumps over the lazy dog';

// 基本替换(只替换第一个匹配)
const replaced1 = text.replace('the', 'a');
console.log(replaced1);                 // 'The quick brown fox jumps over a lazy dog'

// 使用正则表达式替换所有匹配
const replaced2 = text.replace(/the/g, 'a');
console.log(replaced2);                 // 'The quick brown fox jumps over a lazy dog'

// 忽略大小写替换
const replaced3 = text.replace(/the/gi, 'a');
console.log(replaced3);                 // 'a quick brown fox jumps over a lazy dog'

// 使用函数进行替换
const replaced4 = text.replace(/\b\w{4}\b/g, (match) => {
  return match.toUpperCase();
});
console.log(replaced4);                 // 将4个字母的单词转为大写

// 复杂的替换逻辑
const template = 'Hello {{name}}, you have {{count}} messages';
const data = { name: 'Alice', count: 5 };

const result = template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
  return data[key] || match;
});
console.log(result);                    // 'Hello Alice, you have 5 messages'

// replaceAll方法(ES2021)
const text2 = 'cat and cat and cat';
const allReplaced = text2.replaceAll('cat', 'dog');
console.log(allReplaced);               // 'dog and dog and dog'

// 去除空白字符
const messyText = '  \n\t  Hello World  \n\t  ';
console.log(messyText.trim());          // 'Hello World'
console.log(messyText.trimStart());     // 'Hello World  \n\t  '
console.log(messyText.trimEnd());       // '  \n\t  Hello World'

// 自定义trim函数
function customTrim(str, chars = ' \t\n\r') {
  const start = str.search(new RegExp(`[^${chars.replace(/[\\\]\-^]/g, '\\$&')}]`));
  if (start === -1) return '';
  
  const end = str.search(new RegExp(`[^${chars.replace(/[\\\]\-^]/g, '\\$&')}]\s*$`));
  return str.slice(start, end + 1);
}

console.log(customTrim('...Hello World...', '.'));  // 'Hello World'

// 字符串格式化
function formatString(template, ...args) {
  return template.replace(/{(\d+)}/g, (match, index) => {
    return args[index] !== undefined ? args[index] : match;
  });
}

const formatted = formatString('Hello {0}, you are {1} years old', 'Alice', 25);
console.log(formatted);                 // 'Hello Alice, you are 25 years old'

// 驼峰命名转换
function toCamelCase(str) {
  return str.replace(/[-_\s]+(.)?/g, (match, char) => {
    return char ? char.toUpperCase() : '';
  });
}

function toKebabCase(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

function toSnakeCase(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
}

console.log(toCamelCase('hello-world-test'));    // 'helloWorldTest'
console.log(toKebabCase('helloWorldTest'));      // 'hello-world-test'
console.log(toSnakeCase('helloWorldTest'));      // 'hello_world_test'

// HTML转义
function escapeHtml(str) {
  const htmlEscapes = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;'
  };
  
  return str.replace(/[&<>"']/g, (match) => htmlEscapes[match]);
}

function unescapeHtml(str) {
  const htmlUnescapes = {
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&#39;': "'"
  };
  
  return str.replace(/&(?:amp|lt|gt|quot|#39);/g, (match) => htmlUnescapes[match]);
}

const htmlString = '<div class="test">Hello & goodbye</div>';
console.log(escapeHtml(htmlString));
console.log(unescapeHtml(escapeHtml(htmlString)));

模板字符串

基本语法和插值

// 基本模板字符串
const name = 'Alice';
const age = 25;
const greeting = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(greeting);

// 多行字符串
const multiline = `
  This is a
  multi-line
  string
`;
console.log(multiline);

// 表达式插值
const a = 10;
const b = 20;
const result = `The sum of ${a} and ${b} is ${a + b}`;
console.log(result);

// 函数调用插值
function formatCurrency(amount) {
  return `$${amount.toFixed(2)}`;
}

const price = 19.99;
const message = `The price is ${formatCurrency(price)}`;
console.log(message);

// 条件表达式
const user = { name: 'Bob', isAdmin: true };
const status = `User ${user.name} is ${user.isAdmin ? 'an admin' : 'a regular user'}`;
console.log(status);

// 嵌套模板字符串
const items = ['apple', 'banana', 'orange'];
const list = `
  <ul>
    ${items.map(item => `<li>${item}</li>`).join('\n    ')}
  </ul>
`;
console.log(list);

// 对象属性访问
const person = {
  firstName: 'John',
  lastName: 'Doe',
  address: {
    city: 'New York',
    country: 'USA'
  }
};

const info = `${person.firstName} ${person.lastName} lives in ${person.address.city}, ${person.address.country}`;
console.log(info);

// 数组操作
const numbers = [1, 2, 3, 4, 5];
const summary = `Numbers: [${numbers.join(', ')}], Sum: ${numbers.reduce((a, b) => a + b)}`;
console.log(summary);

标签模板

// 基本标签模板
function highlight(strings, ...values) {
  return strings.reduce((result, string, i) => {
    const value = values[i] ? `<mark>${values[i]}</mark>` : '';
    return result + string + value;
  }, '');
}

const searchTerm = 'JavaScript';
const text = highlight`I love ${searchTerm} programming!`;
console.log(text); // 'I love <mark>JavaScript</mark> programming!'

// 安全的HTML模板
function safeHtml(strings, ...values) {
  const escapeHtml = (str) => {
    return String(str)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  };
  
  return strings.reduce((result, string, i) => {
    const value = values[i] ? escapeHtml(values[i]) : '';
    return result + string + value;
  }, '');
}

const userInput = '<script>alert("XSS")</script>';
const safeOutput = safeHtml`User input: ${userInput}`;
console.log(safeOutput); // 转义后的安全输出

// 国际化标签模板
const translations = {
  en: {
    greeting: 'Hello {0}!',
    farewell: 'Goodbye {0}!'
  },
  es: {
    greeting: '¡Hola {0}!',
    farewell: '¡Adiós {0}!'
  }
};

function i18n(locale) {
  return function(strings, ...values) {
    const key = strings.join('{placeholder}').replace(/\s+/g, '_').toLowerCase();
    let template = translations[locale]?.[key] || strings.join('{placeholder}');
    
    values.forEach((value, index) => {
      template = template.replace(`{${index}}`, value);
    });
    
    return template;
  };
}

const t_en = i18n('en');
const t_es = i18n('es');

const userName = 'Alice';
console.log(t_en`greeting ${userName}`);
console.log(t_es`greeting ${userName}`);

// SQL查询构建器(注意:实际应用中应使用参数化查询)
function sql(strings, ...values) {
  const query = strings.reduce((result, string, i) => {
    const value = values[i];
    let processedValue = '';
    
    if (value !== undefined) {
      if (typeof value === 'string') {
        processedValue = `'${value.replace(/'/g, "''")}'`; // 简单的SQL转义
      } else if (typeof value === 'number') {
        processedValue = value.toString();
      } else if (Array.isArray(value)) {
        processedValue = value.map(v => typeof v === 'string' ? `'${v}'` : v).join(', ');
      }
    }
    
    return result + string + processedValue;
  }, '');
  
  return { query, execute: () => console.log('Executing:', query) };
}

const userId = 123;
const status = 'active';
const categories = ['tech', 'science'];

const queryBuilder = sql`
  SELECT * FROM users 
  WHERE id = ${userId} 
    AND status = ${status}
    AND category IN (${categories})
`;

queryBuilder.execute();

// 样式化控制台输出
function styled(strings, ...values) {
  const styles = [];
  let result = '';
  
  strings.forEach((string, i) => {
    result += string;
    
    if (values[i] !== undefined) {
      const value = values[i];
      if (typeof value === 'object' && value.style) {
        result += '%c' + value.text + '%c';
        styles.push(value.style, '');
      } else {
        result += value;
      }
    }
  });
  
  return { text: result, styles };
}

const styledMessage = styled`
  Hello ${{ text: 'World', style: 'color: red; font-weight: bold' }}!
  This is ${{ text: 'awesome', style: 'color: blue; text-decoration: underline' }}!
`;

console.log(styledMessage.text, ...styledMessage.styles);

// 模板缓存
const templateCache = new Map();

function cachedTemplate(strings, ...values) {
  const key = strings.join('\x00');
  
  if (!templateCache.has(key)) {
    const template = strings.reduce((result, string, i) => {
      return result + string + (i < values.length ? `\${${i}}` : '');
    }, '');
    templateCache.set(key, template);
  }
  
  let result = templateCache.get(key);
  values.forEach((value, index) => {
    result = result.replace(`\${${index}}`, value);
  });
  
  return result;
}

// 使用缓存模板
const template1 = cachedTemplate`Hello ${name}!`;
const template2 = cachedTemplate`Hello ${name}!`; // 使用缓存
console.log(template1, template2);

正则表达式基础

正则表达式语法

// 创建正则表达式
const regex1 = /pattern/flags;          // 字面量语法(推荐)
const regex2 = new RegExp('pattern', 'flags'); // 构造函数语法

// 基本匹配
const text = 'Hello World 123';
const simplePattern = /World/;
console.log(simplePattern.test(text));  // true
console.log(text.match(simplePattern)); // ['World', index: 6, input: 'Hello World 123', groups: undefined]

// 常用标志
const globalPattern = /o/g;             // g: 全局匹配
const caseInsensitive = /hello/i;       // i: 忽略大小写
const multiline = /^world/m;            // m: 多行模式
const dotAll = /hello.world/s;          // s: 点号匹配换行符
const unicode = /\u{1F600}/u;           // u: Unicode模式
const sticky = /hello/y;                // y: 粘性匹配

// 字符类
const digitPattern = /\d+/;             // \d: 数字 [0-9]
const wordPattern = /\w+/;              // \w: 单词字符 [a-zA-Z0-9_]
const whitespacePattern = /\s+/;        // \s: 空白字符
const nonDigitPattern = /\D+/;          // \D: 非数字
const nonWordPattern = /\W+/;           // \W: 非单词字符
const nonWhitespacePattern = /\S+/;     // \S: 非空白字符

// 自定义字符类
const vowelPattern = /[aeiou]/i;        // 匹配元音字母
const consonantPattern = /[^aeiou]/i;   // 匹配辅音字母
const rangePattern = /[a-z0-9]/;        // 匹配小写字母或数字
const specialPattern = /[.?!]/;         // 匹配特定字符

// 量词
const zeroOrMore = /a*/;                // *: 0次或多次
const oneOrMore = /a+/;                 // +: 1次或多次
const zeroOrOne = /a?/;                 // ?: 0次或1次
const exactCount = /a{3}/;              // {n}: 恰好n次
const rangeCount = /a{2,5}/;            // {n,m}: n到m次
const minCount = /a{2,}/;               // {n,}: 至少n次

// 锚点
const startPattern = /^Hello/;          // ^: 行开始
const endPattern = /World$/;            // $: 行结束
const wordBoundary = /\bword\b/;        // \b: 单词边界
const nonWordBoundary = /\Btest\B/;     // \B: 非单词边界

// 分组和捕获
const groupPattern = /(\d{4})-(\d{2})-(\d{2})/; // 捕获组
const nonCapturingGroup = /(?:\d{4})-(?:\d{2})-(?:\d{2})/; // 非捕获组
const namedGroup = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; // 命名捕获组

// 测试日期匹配
const dateString = '2023-12-25';
const dateMatch = dateString.match(groupPattern);
console.log(dateMatch); // ['2023-12-25', '2023', '12', '25', ...]

const namedMatch = dateString.match(namedGroup);
console.log(namedMatch.groups); // { year: '2023', month: '12', day: '25' }

// 选择和前瞻
const alternation = /cat|dog/;          // |: 选择
const positiveLookahead = /\d+(?=px)/;  // (?=): 正向前瞻
const negativeLookahead = /\d+(?!px)/;  // (?!): 负向前瞻
const positiveLookbehind = /(?<=\$)\d+/; // (?<=): 正向后瞻
const negativeLookbehind = /(?<!\$)\d+/; // (?<!): 负向后瞻

// 测试前瞻和后瞻
const cssText = 'width: 100px; height: 200em; margin: 50;';
console.log(cssText.match(/\d+(?=px)/g)); // ['100'] - 只匹配后面跟px的数字
console.log(cssText.match(/\d+(?!px)/g)); // ['200', '50'] - 匹配后面不跟px的数字

字符串方法中的正则表达式

const text = 'The quick brown fox jumps over the lazy dog. The fox is quick.';

// match方法
const singleMatch = text.match(/fox/);
console.log(singleMatch); // ['fox', index: 16, input: '...', groups: undefined]

const globalMatch = text.match(/the/gi);
console.log(globalMatch); // ['The', 'the', 'The']

const noMatch = text.match(/cat/);
console.log(noMatch); // null

// matchAll方法(ES2020)
const pattern = /t(h)e/gi;
const allMatches = [...text.matchAll(pattern)];
console.log(allMatches); // 包含所有匹配的详细信息

// search方法
const firstIndex = text.search(/fox/);
console.log(firstIndex); // 16

const notFoundIndex = text.search(/cat/);
console.log(notFoundIndex); // -1

// replace方法
const replaced = text.replace(/fox/g, 'cat');
console.log(replaced);

// 使用捕获组替换
const dateText = 'Today is 2023-12-25';
const reformatted = dateText.replace(
  /(\d{4})-(\d{2})-(\d{2})/,
  '$2/$3/$1' // 使用$1, $2, $3引用捕获组
);
console.log(reformatted); // 'Today is 12/25/2023'

// 使用函数进行复杂替换
const phoneText = 'Call me at 123-456-7890 or 987-654-3210';
const formattedPhones = phoneText.replace(
  /(\d{3})-(\d{3})-(\d{4})/g,
  (match, area, exchange, number) => {
    return `(${area}) ${exchange}-${number}`;
  }
);
console.log(formattedPhones); // 'Call me at (123) 456-7890 or (987) 654-3210'

// split方法
const csvLine = 'apple,banana,orange,grape';
const fruits = csvLine.split(/,/);
console.log(fruits); // ['apple', 'banana', 'orange', 'grape']

// 复杂分割
const mixedSeparators = 'apple,banana;orange:grape';
const mixedFruits = mixedSeparators.split(/[,;:]/);
console.log(mixedFruits); // ['apple', 'banana', 'orange', 'grape']

// 保留分隔符
const sentence = 'Hello world! How are you? Fine, thanks.';
const sentences = sentence.split(/([.!?])/).filter(s => s.trim());
console.log(sentences); // ['Hello world', '!', ' How are you', '?', ' Fine, thanks', '.']

// test方法
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(emailPattern.test('user@example.com')); // true
console.log(emailPattern.test('invalid-email'));   // false

// exec方法
const globalPattern = /\d+/g;
let match;
while ((match = globalPattern.exec('There are 123 apples and 456 oranges')) !== null) {
  console.log(`Found ${match[0]} at position ${match.index}`);
}

常用正则表达式模式

// 验证模式
const patterns = {
  // 邮箱验证
  email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
  
  // 手机号验证(中国)
  chinesePhone: /^1[3-9]\d{9}$/,
  
  // 美国手机号
  usPhone: /^\+?1?[-.\s]?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$/,
  
  // 密码强度(至少8位,包含大小写字母、数字和特殊字符)
  strongPassword: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,
  
  // URL验证
  url: /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/,
  
  // IPv4地址
  ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
  
  // 身份证号(中国)
  chineseId: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
  
  // 信用卡号
  creditCard: /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3[0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$/,
  
  // 十六进制颜色
  hexColor: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
  
  // 日期格式 YYYY-MM-DD
  date: /^\d{4}-\d{2}-\d{2}$/,
  
  // 时间格式 HH:MM:SS
  time: /^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
  
  // HTML标签
  htmlTag: /<\/?[a-z][\s\S]*>/i,
  
  // 中文字符
  chinese: /[\u4e00-\u9fa5]/,
  
  // 数字(包括小数)
  number: /^-?\d+(\.\d+)?$/,
  
  // 正整数
  positiveInteger: /^[1-9]\d*$/,
  
  // 邮政编码(中国)
  chinesePostalCode: /^[1-9]\d{5}$/,
  
  // 用户名(字母开头,可包含字母数字下划线,3-16位)
  username: /^[a-zA-Z][a-zA-Z0-9_]{2,15}$/
};

// 验证函数
function validate(type, value) {
  const pattern = patterns[type];
  if (!pattern) {
    throw new Error(`Unknown validation type: ${type}`);
  }
  return pattern.test(value);
}

// 使用示例
console.log(validate('email', 'user@example.com'));     // true
console.log(validate('email', 'invalid-email'));       // false
console.log(validate('chinesePhone', '13812345678'));   // true
console.log(validate('strongPassword', 'MyPass123!'));  // true

// 提取信息的正则表达式
function extractEmails(text) {
  const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
  return text.match(emailRegex) || [];
}

function extractUrls(text) {
  const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
  return text.match(urlRegex) || [];
}

function extractPhoneNumbers(text) {
  const phoneRegex = /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g;
  return text.match(phoneRegex) || [];
}

// 测试提取功能
const sampleText = `
  Contact us at support@example.com or sales@company.org.
  Visit our website: https://www.example.com
  Call us: 123-456-7890 or 987.654.3210
`;

console.log('Emails:', extractEmails(sampleText));
console.log('URLs:', extractUrls(sampleText));
console.log('Phones:', extractPhoneNumbers(sampleText));

// 文本清理和格式化
function cleanText(text) {
  return text
    .replace(/\s+/g, ' ')           // 多个空白字符替换为单个空格
    .replace(/[^\w\s.,!?-]/g, '')   // 移除特殊字符
    .trim();                        // 去除首尾空白
}

function formatPhoneNumber(phone) {
  const cleaned = phone.replace(/\D/g, '');
  if (cleaned.length === 10) {
    return cleaned.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
  }
  return phone;
}

function maskCreditCard(cardNumber) {
  const cleaned = cardNumber.replace(/\D/g, '');
  if (cleaned.length >= 13) {
    return cleaned.replace(/(\d{4})(\d+)(\d{4})/, '$1-****-****-$3');
  }
  return cardNumber;
}

// 高级文本处理
function highlightKeywords(text, keywords) {
  let result = text;
  keywords.forEach(keyword => {
    const regex = new RegExp(`\\b${keyword}\\b`, 'gi');
    result = result.replace(regex, `<mark>$&</mark>`);
  });
  return result;
}

function truncateText(text, maxLength, suffix = '...') {
  if (text.length <= maxLength) return text;
  
  const truncated = text.slice(0, maxLength - suffix.length);
  const lastSpace = truncated.lastIndexOf(' ');
  
  return (lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated) + suffix;
}

function wordCount(text) {
  const words = text.trim().split(/\s+/);
  return words[0] === '' ? 0 : words.length;
}

function readingTime(text, wordsPerMinute = 200) {
  const words = wordCount(text);
  const minutes = Math.ceil(words / wordsPerMinute);
  return `${minutes} min read`;
}

// 测试高级文本处理
const article = 'JavaScript is a powerful programming language. It is widely used for web development.';
console.log(highlightKeywords(article, ['JavaScript', 'programming']));
console.log(truncateText(article, 50));
console.log('Word count:', wordCount(article));
console.log('Reading time:', readingTime(article));

数组和字符串的性能优化

性能最佳实践

// 数组性能优化

// 1. 预分配数组大小(当知道最终大小时)
function createLargeArray(size) {
  // 好的做法
  const arr = new Array(size);
  for (let i = 0; i < size; i++) {
    arr[i] = i;
  }
  return arr;
}

// 2. 避免在循环中使用push(当知道大小时)
function inefficientArrayCreation(size) {
  const arr = [];
  for (let i = 0; i < size; i++) {
    arr.push(i); // 每次push可能触发数组重新分配
  }
  return arr;
}

// 3. 使用适当的数组方法
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 查找单个元素时,使用find而不是filter
const found = numbers.find(n => n > 5);        // 找到第一个就停止
const filtered = numbers.filter(n => n > 5)[0]; // 遍历整个数组

// 检查存在性时,使用some而不是filter
const exists = numbers.some(n => n > 5);        // 找到第一个就返回true
const hasItems = numbers.filter(n => n > 5).length > 0; // 遍历整个数组

// 4. 避免不必要的数组复制
function processArray(arr) {
  // 如果不需要保留原数组,直接修改
  return arr.sort((a, b) => a - b);
  
  // 如果需要保留原数组,创建副本
  // return [...arr].sort((a, b) => a - b);
}

// 5. 使用TypedArray处理大量数值数据
function createTypedArray(size) {
  const arr = new Float32Array(size);
  for (let i = 0; i < size; i++) {
    arr[i] = Math.random();
  }
  return arr;
}

// 字符串性能优化

// 1. 使用数组join而不是字符串连接(大量拼接时)
function inefficientStringConcat(items) {
  let result = '';
  for (const item of items) {
    result += item + ', '; // 每次连接都创建新字符串
  }
  return result.slice(0, -2);
}

function efficientStringConcat(items) {
  return items.join(', '); // 一次性连接
}

// 2. 使用模板字符串进行复杂拼接
function buildHtml(items) {
  // 使用数组和join
  return items.map(item => `<li>${item}</li>`).join('');
  
  // 或者使用模板字符串
  // return `<ul>${items.map(item => `<li>${item}</li>`).join('')}</ul>`;
}

// 3. 缓存正则表达式
class TextProcessor {
  constructor() {
    // 缓存常用正则表达式
    this.emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
    this.phoneRegex = /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g;
  }
  
  extractEmails(text) {
    return text.match(this.emailRegex) || [];
  }
  
  extractPhones(text) {
    return text.match(this.phoneRegex) || [];
  }
}

// 4. 避免不必要的字符串操作
function processText(text) {
  // 链式操作一次完成
  return text
    .toLowerCase()
    .trim()
    .replace(/\s+/g, ' ');
    
  // 避免多次赋值
  // text = text.toLowerCase();
  // text = text.trim();
  // text = text.replace(/\s+/g, ' ');
  // return text;
}

// 性能测试工具
function benchmark(name, fn, iterations = 1000) {
  const start = performance.now();
  
  for (let i = 0; i < iterations; i++) {
    fn();
  }
  
  const end = performance.now();
  console.log(`${name}: ${(end - start).toFixed(2)}ms`);
}

// 测试示例
const testData = Array.from({ length: 10000 }, (_, i) => i);
const testStrings = Array.from({ length: 1000 }, (_, i) => `item${i}`);

benchmark('Array find', () => testData.find(n => n > 5000));
benchmark('Array filter[0]', () => testData.filter(n => n > 5000)[0]);

benchmark('String join', () => efficientStringConcat(testStrings));
benchmark('String concat', () => inefficientStringConcat(testStrings));

内存管理

// 避免内存泄漏

// 1. 及时清理大数组
function processLargeData() {
  let largeArray = new Array(1000000).fill(0);
  
  // 处理数据
  const result = largeArray.map(x => x * 2);
  
  // 清理引用
  largeArray = null;
  
  return result;
}

// 2. 使用WeakMap避免循环引用
const cache = new WeakMap();

function expensiveOperation(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  }
  
  const result = /* 复杂计算 */ obj.value * 2;
  cache.set(obj, result);
  return result;
}

// 3. 分批处理大数据
function processBatches(largeArray, batchSize = 1000) {
  const results = [];
  
  for (let i = 0; i < largeArray.length; i += batchSize) {
    const batch = largeArray.slice(i, i + batchSize);
    const batchResult = batch.map(item => item * 2);
    results.push(...batchResult);
    
    // 给浏览器喘息机会
    if (i % (batchSize * 10) === 0) {
      setTimeout(() => {}, 0);
    }
  }
  
  return results;
}

// 4. 使用生成器处理大数据
function* processLargeDataGenerator(largeArray) {
  for (const item of largeArray) {
    yield item * 2;
  }
}

// 使用生成器
function consumeGenerator(generator) {
  const results = [];
  for (const value of generator) {
    results.push(value);
    
    // 可以在这里添加中断逻辑
    if (results.length >= 1000) {
      break;
    }
  }
  return results;
}

// 5. 字符串内存优化
function optimizeStringMemory() {
  // 避免创建大量临时字符串
  const parts = [];
  
  for (let i = 0; i < 1000; i++) {
    parts.push(`Item ${i}`);
  }
  
  // 一次性连接
  return parts.join('\n');
}

// 6. 使用Object.freeze减少意外修改
function createImmutableArray(data) {
  return Object.freeze([...data]);
}

function createDeepImmutableArray(data) {
  return Object.freeze(
    data.map(item => 
      typeof item === 'object' ? Object.freeze({ ...item }) : item
    )
  );
}

实际应用示例

数据处理管道

// 构建数据处理管道
class DataPipeline {
  constructor(data) {
    this.data = data;
  }
  
  filter(predicate) {
    this.data = this.data.filter(predicate);
    return this;
  }
  
  map(transform) {
    this.data = this.data.map(transform);
    return this;
  }
  
  sort(compareFn) {
    this.data = this.data.sort(compareFn);
    return this;
  }
  
  groupBy(keyFn) {
    const groups = {};
    this.data.forEach(item => {
      const key = keyFn(item);
      if (!groups[key]) {
        groups[key] = [];
      }
      groups[key].push(item);
    });
    this.data = groups;
    return this;
  }
  
  take(count) {
    this.data = this.data.slice(0, count);
    return this;
  }
  
  result() {
    return this.data;
  }
}

// 使用数据管道
const salesData = [
  { id: 1, product: 'Laptop', category: 'Electronics', price: 999, date: '2023-01-15' },
  { id: 2, product: 'Phone', category: 'Electronics', price: 599, date: '2023-01-16' },
  { id: 3, product: 'Book', category: 'Education', price: 29, date: '2023-01-17' },
  { id: 4, product: 'Headphones', category: 'Electronics', price: 199, date: '2023-01-18' },
  { id: 5, product: 'Notebook', category: 'Education', price: 5, date: '2023-01-19' }
];

const expensiveElectronics = new DataPipeline(salesData)
  .filter(item => item.category === 'Electronics')
  .filter(item => item.price > 500)
  .sort((a, b) => b.price - a.price)
  .map(item => ({ ...item, formattedPrice: `$${item.price}` }))
  .result();

console.log('Expensive Electronics:', expensiveElectronics);

// 文本分析工具
class TextAnalyzer {
  constructor(text) {
    this.text = text;
    this.words = this.extractWords();
  }
  
  extractWords() {
    return this.text
      .toLowerCase()
      .replace(/[^\w\s]/g, '')
      .split(/\s+/)
      .filter(word => word.length > 0);
  }
  
  wordFrequency() {
    const frequency = {};
    this.words.forEach(word => {
      frequency[word] = (frequency[word] || 0) + 1;
    });
    return frequency;
  }
  
  mostCommonWords(count = 10) {
    const frequency = this.wordFrequency();
    return Object.entries(frequency)
      .sort(([,a], [,b]) => b - a)
      .slice(0, count)
      .map(([word, freq]) => ({ word, frequency: freq }));
  }
  
  wordCount() {
    return this.words.length;
  }
  
  uniqueWordCount() {
    return new Set(this.words).size;
  }
  
  averageWordLength() {
    const totalLength = this.words.reduce((sum, word) => sum + word.length, 0);
    return totalLength / this.words.length;
  }
  
  readabilityScore() {
    const sentences = this.text.split(/[.!?]+/).filter(s => s.trim().length > 0);
    const avgWordsPerSentence = this.words.length / sentences.length;
    const avgSyllablesPerWord = this.averageWordLength() / 2; // 简化计算
    
    // 简化的Flesch Reading Ease公式
    return 206.835 - (1.015 * avgWordsPerSentence) - (84.6 * avgSyllablesPerWord);
  }
}

// 使用文本分析器
const sampleText = `
  JavaScript is a versatile programming language that runs in web browsers and servers.
  It supports multiple programming paradigms including object-oriented, functional, and procedural programming.
  JavaScript is widely used for web development, mobile app development, and even desktop applications.
`;

const analyzer = new TextAnalyzer(sampleText);
console.log('Word count:', analyzer.wordCount());
console.log('Unique words:', analyzer.uniqueWordCount());
console.log('Average word length:', analyzer.averageWordLength().toFixed(2));
console.log('Most common words:', analyzer.mostCommonWords(5));
console.log('Readability score:', analyzer.readabilityScore().toFixed(2));

本章总结

本章深入探讨了JavaScript中数组和字符串的处理方法:

  1. 数组基础:学习了数组的创建、操作、查找和检测方法
  2. 数组高阶方法:掌握了map、filter、reduce等函数式编程方法
  3. 字符串基础:了解了字符串的创建、查找、提取和修改操作
  4. 模板字符串:学习了ES6模板字符串的语法和标签模板的高级用法
  5. 正则表达式:掌握了正则表达式的基本语法和在字符串处理中的应用
  6. 性能优化:了解了数组和字符串操作的性能最佳实践
  7. 实际应用:通过数据处理管道和文本分析工具展示了实际应用场景

数组和字符串是JavaScript中最常用的数据类型,熟练掌握它们的操作方法对于编写高效的JavaScript代码至关重要。这些知识为后续学习DOM操作、异步编程等高级主题奠定了坚实基础。

下一章我们将学习JavaScript的异步编程,包括回调函数、Promise和async/await。