1. JavaScript数组深度解析
1.1 数组基础与创建方式
在JavaScript中,数组是最常用的数据结构之一,它允许我们在单个变量中存储多个值。与Java等强类型语言不同,JS数组可以同时包含不同类型的数据,这种灵活性既是优势也可能成为陷阱。
创建数组的三种典型方式:
javascript复制// 方式1:数组字面量(推荐)
let fruits = ['Apple', 'Banana', 'Orange'];
// 方式2:Array构造函数
let numbers = new Array(1, 2, 3);
// 方式3:ES6的Array.of()
let mixed = Array.of(1, 'text', true);
实际开发中发现:使用
new Array(5)会创建长度为5的空数组(俗称稀疏数组),而Array.of(5)创建的是包含单个元素5的数组,这个差异经常导致初学者踩坑。
1.2 核心数组方法实战
现代JavaScript提供了丰富的数组方法,以下分类说明最常用的几类:
遍历类方法:
javascript复制// forEach - 最基础的遍历
[1, 2, 3].forEach(item => console.log(item));
// map - 映射新数组
const doubled = [1, 2, 3].map(x => x * 2);
// filter - 条件过滤
const evens = [1, 2, 3].filter(x => x % 2 === 0);
增删改查方法:
javascript复制// push/pop - 尾部操作
let stack = [];
stack.push(1); // [1]
stack.pop(); // []
// splice - 万能修改
let arr = [1, 2, 3];
arr.splice(1, 1, 'a', 'b'); // [1, 'a', 'b', 3]
ES6+新增方法:
javascript复制// includes - 包含检测
[1, 2, 3].includes(2); // true
// find/findIndex - 条件查找
[1, 2, 3].find(x => x > 1); // 2
// flat - 数组扁平化
[1, [2, [3]]].flat(2); // [1, 2, 3]
1.3 性能优化与陷阱规避
在实际项目中处理大数据量时,数组操作性能至关重要:
-
循环选择:for循环 > forEach > map
- 实测10万次迭代:for循环比map快约60%
-
内存优化:
javascript复制// 错误示范:频繁concat创建新数组 let result = []; for(let i=0; i<10000; i++){ result = result.concat([i]); } // 正确做法:预分配长度 let result = new Array(10000); for(let i=0; i<10000; i++){ result[i] = i; } -
类型一致数组:V8引擎会对同类型数组进行优化,混合类型数组性能下降明显
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JavaScript函数全面掌握
2.1 函数定义与调用模式
JavaScript的函数比其他语言更加灵活,主要体现在定义方式和this绑定上:
四种定义方式对比:
| 方式 | 示例 | 特性 |
|---|---|---|
| 函数声明 | function sum(a,b){...} |
存在提升 |
| 函数表达式 | const sum = function(){} |
匿名函数 |
| 箭头函数 | const sum = (a,b)=>a+b |
无this绑定 |
| 构造函数 | new Function('a','b','return a+b') |
动态创建 |
this指向的经典问题:
javascript复制const obj = {
name: 'Object',
print: function(){
console.log(this.name);
},
printArrow: () => {
console.log(this.name); // 指向window!
}
};
2.2 参数处理高级技巧
JavaScript函数的参数处理非常灵活,但也容易产生混淆:
剩余参数与arguments对象:
javascript复制// ES6剩余参数
function sum(...numbers) {
return numbers.reduce((a,b) => a+b);
}
// 传统arguments
function oldSum() {
let total = 0;
for(let i=0; i<arguments.length; i++){
total += arguments[i];
}
return total;
}
关键区别:剩余参数是真正的Array实例,而arguments是类数组对象。在ES6环境中建议始终使用剩余参数。
默认参数的高级用法:
javascript复制function createElement(type, {
color = 'red',
size = 'medium'
} = {}) {
console.log(`创建${color}色${size}号的${type}`);
}
2.3 闭包与高阶函数实战
闭包是JavaScript最强大的特性之一,也是面试必问知识点:
经典闭包示例:
javascript复制function createCounter() {
let count = 0;
return {
increment: () => ++count,
get: () => count
};
}
const counter = createCounter();
counter.increment(); // 1
高阶函数应用:
javascript复制// 函数工厂
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
double(5); // 10
内存泄漏警示:
javascript复制// 错误示范:DOM元素引用未清理
function setupButton() {
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('Button clicked!');
});
}
// 即使移除button,回调函数仍保持对DOM元素的引用
3. 数组与函数的结合应用
3.1 函数式编程实践
现代JavaScript开发越来越倾向于函数式风格,数组方法为此提供了良好支持:
数据处理管道:
javascript复制const transactions = [
{ id: 1, amount: 100, currency: 'USD' },
{ id: 2, amount: 200, currency: 'EUR' },
{ id: 3, amount: 300, currency: 'USD' }
];
const totalUSD = transactions
.filter(tx => tx.currency === 'USD')
.map(tx => tx.amount)
.reduce((sum, amount) => sum + amount, 0);
自定义高阶函数:
javascript复制function compose(...fns) {
return fns.reduce((f, g) => (...args) => f(g(...args)));
}
const add5 = x => x + 5;
const multiply2 = x => x * 2;
const operation = compose(add5, multiply2);
operation(10); // 25 (10*2+5)
3.2 常见算法实现
面试中常见的数组相关算法题,用函数式方法实现更简洁:
数组去重:
javascript复制// ES6 Set方案
const unique = arr => [...new Set(arr)];
// filter方案
const unique = arr => arr.filter((item, index) => arr.indexOf(item) === index);
扁平化实现:
javascript复制function flattenDeep(arr) {
return arr.reduce(
(acc, val) => acc.concat(Array.isArray(val) ? flattenDeep(val) : val),
[]
);
}
快速排序:
javascript复制function quickSort(arr) {
if (arr.length <= 1) return arr;
const pivot = arr[0];
const left = [];
const right = [];
for (let i = 1; i < arr.length; i++) {
arr[i] < pivot ? left.push(arr[i]) : right.push(arr[i]);
}
return [...quickSort(left), pivot, ...quickSort(right)];
}
4. 实战问题排查与性能优化
4.1 常见错误类型
类型混淆错误:
javascript复制// 错误:将类数组当作真实数组
function printArguments() {
arguments.forEach(arg => console.log(arg)); // TypeError!
}
// 修复方案:
function printArguments() {
Array.from(arguments).forEach(arg => console.log(arg));
}
异步陷阱:
javascript复制// 错误:在循环中使用异步回调
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // 输出5个5!
}
// 正确方案:
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100);
}
4.2 性能优化技巧
大数据处理策略:
- 分批处理:
javascript复制function processLargeArray(arr, chunkSize, processFn) {
let index = 0;
function next() {
const chunk = arr.slice(index, index + chunkSize);
if (chunk.length) {
processFn(chunk);
index += chunkSize;
setTimeout(next, 0); // 释放事件循环
}
}
next();
}
- Web Worker并行:
javascript复制// main.js
const worker = new Worker('worker.js');
worker.postMessage(largeArray);
worker.onmessage = e => console.log(e.data);
// worker.js
self.onmessage = e => {
const result = processArray(e.data);
self.postMessage(result);
};
内存优化方案:
- 避免内存泄漏:
javascript复制// 事件监听器及时移除
element.addEventListener('click', handler);
// 不再需要时:
element.removeEventListener('click', handler);
- 大数组处理:
javascript复制// 原始数组处理可能内存不足
const hugeArray = new Array(1e7).fill(0);
// 改为流式处理
function* generateHugeData() {
for(let i=0; i<1e7; i++) {
yield i;
}
}
在真实项目开发中,数组和函数的组合使用几乎无处不在。掌握它们的各种特性和最佳实践,能够显著提升代码质量和开发效率。特别是在处理复杂业务逻辑时,合理运用函数式编程思想,配合数组的高阶方法,往往能让代码更加简洁优雅。
