数组基础
数组创建和基本操作
// 数组创建方式
// 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 = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return str.replace(/[&<>"']/g, (match) => htmlEscapes[match]);
}
function unescapeHtml(str) {
const htmlUnescapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
''': "'"
};
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, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
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中数组和字符串的处理方法:
- 数组基础:学习了数组的创建、操作、查找和检测方法
- 数组高阶方法:掌握了map、filter、reduce等函数式编程方法
- 字符串基础:了解了字符串的创建、查找、提取和修改操作
- 模板字符串:学习了ES6模板字符串的语法和标签模板的高级用法
- 正则表达式:掌握了正则表达式的基本语法和在字符串处理中的应用
- 性能优化:了解了数组和字符串操作的性能最佳实践
- 实际应用:通过数据处理管道和文本分析工具展示了实际应用场景
数组和字符串是JavaScript中最常用的数据类型,熟练掌握它们的操作方法对于编写高效的JavaScript代码至关重要。这些知识为后续学习DOM操作、异步编程等高级主题奠定了坚实基础。
下一章我们将学习JavaScript的异步编程,包括回调函数、Promise和async/await。