javascript 入门指南
# 学习目标
本大纲旨在为 JavaScript 初学者提供系统性的学习路径,从基础语法到现代开发,逐步掌握 JavaScript 编程技能。
# 1. JavaScript 基础语法
# 1.1 环境搭建
- Node.js 安装和配置
- 浏览器开发者工具使用
- 代码编辑器选择和配置(VS Code, WebStorm)
- 包管理工具(npm, yarn)
- 模块打包工具(Webpack, Vite)
# 1.2 基本概念
- JavaScript 简介和特点
- 第一个 JavaScript 程序
- 代码注释和文档字符串
- 代码规范和 ESLint
# 1.3 数据类型
# 原始类型
// 数字
let integer = 42;
let float = 3.14159;
let infinity = Infinity;
let notANumber = NaN;
// 字符串
let singleQuote = 'Hello';
let doubleQuote = "World";
let template = `Hello ${name}`;
// 布尔值
let isTrue = true;
let isFalse = false;
// undefined 和 null
let undefinedVar = undefined;
let nullVar = null;
// Symbol(ES6)
let symbol = Symbol('description');
// BigInt(ES2020)
let bigInt = 9007199254740991n;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 引用类型
// 对象
let person = {
name: 'Alice',
age: 25,
greet() {
return `Hello, I'm ${this.name}`;
}
};
// 数组
let numbers = [1, 2, 3, 4, 5];
let mixed = [1, 'hello', true, { key: 'value' }];
// 函数
function greet(name) {
return `Hello, ${name}!`;
}
// 日期
let now = new Date();
let specificDate = new Date('2024-01-01');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.4 变量和赋值
// 变量声明
var oldWay = 'legacy'; // 函数作用域
let modernWay = 'ES6'; // 块级作用域
const constant = 'immutable'; // 常量
// 解构赋值
let [a, b, c] = [1, 2, 3];
let { name, age } = { name: 'Alice', age: 25 };
// 展开运算符
let arr1 = [1, 2, 3];
let arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]
let obj1 = { x: 1, y: 2 };
let obj2 = { ...obj1, z: 3 }; // { x: 1, y: 2, z: 3 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1.5 运算符
// 算术运算符
let sum = 10 + 5; // 加法
let diff = 10 - 5; // 减法
let product = 10 * 5; // 乘法
let quotient = 10 / 5; // 除法
let remainder = 10 % 3; // 取余
let power = 10 ** 2; // 幂运算
// 比较运算符
let equal = 5 == '5'; // 宽松相等
let strictEqual = 5 === '5'; // 严格相等
let notEqual = 5 != '6'; // 宽松不等
let strictNotEqual = 5 !== '5'; // 严格不等
// 逻辑运算符
let and = true && false; // 逻辑与
let or = true || false; // 逻辑或
let not = !true; // 逻辑非
// 空值合并运算符(ES2020)
let result = null ?? 'default'; // 只有 null 或 undefined 时使用默认值
// 可选链操作符(ES2020)
let value = obj?.prop?.subProp; // 安全访问嵌套属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 2. 控制流程
# 2.1 条件语句
// if 语句
if (condition) {
// 执行代码
}
// if-else 语句
if (condition) {
// 条件为真时执行
} else {
// 条件为假时执行
}
// if-else if-else 语句
if (condition1) {
// 条件1为真时执行
} else if (condition2) {
// 条件2为真时执行
} else {
// 所有条件都为假时执行
}
// 三元运算符
let result = condition ? valueIfTrue : valueIfFalse;
// switch 语句
switch (value) {
case 1:
console.log('One');
break;
case 2:
console.log('Two');
break;
default:
console.log('Default');
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 2.2 循环语句
// for 循环
for (let i = 0; i < 10; i++) {
console.log(i);
}
// for...of 循环(ES6)
for (let item of array) {
console.log(item);
}
// for...in 循环
for (let key in object) {
console.log(key, object[key]);
}
// while 循环
while (condition) {
// 执行代码
}
// do...while 循环
do {
// 执行代码
} while (condition);
// 循环控制
for (let i = 0; i < 10; i++) {
if (i === 5) {
break; // 跳出循环
}
if (i === 2) {
continue; // 跳过当前迭代
}
console.log(i);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 2.3 异常处理
try {
// 可能出错的代码
throw new Error('Something went wrong');
} catch (error) {
// 处理异常
console.error('Error:', error.message);
} finally {
// 无论是否异常都执行
console.log('Cleanup');
}
// 自定义错误
class CustomError extends Error {
constructor(message) {
super(message);
this.name = 'CustomError';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3. 函数和模块
# 3.1 函数定义
// 函数声明
function greet(name) {
return `Hello, ${name}!`;
}
// 函数表达式
const greet = function(name) {
return `Hello, ${name}!`;
};
// 箭头函数(ES6)
const greet = (name) => `Hello, ${name}!`;
// 默认参数
function greet(name = 'World') {
return `Hello, ${name}!`;
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
// 解构参数
function processUser({ name, age, email }) {
console.log(`${name} is ${age} years old`);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3.2 函数高级特性
// 高阶函数
function withLogging(fn) {
return function(...args) {
console.log('Calling function with:', args);
const result = fn(...args);
console.log('Function returned:', result);
return result;
};
}
// 闭包
function createCounter() {
let count = 0;
return function() {
return ++count;
};
}
// 立即执行函数表达式(IIFE)
(function() {
console.log('IIFE executed');
})();
// 生成器函数(ES6)
function* fibonacci() {
let [a, b] = [0, 1];
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 3.3 模块系统
// ES6 模块
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export default class Calculator {
add(a, b) { return a + b; }
}
// main.js
import Calculator, { add, subtract } from './math.js';
import * as math from './math.js';
// CommonJS(Node.js)
// math.js
module.exports = {
add: (a, b) => a + b,
subtract: (a, b) => a - b
};
// main.js
const math = require('./math.js');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 4. 面向对象编程
# 4.1 类和对象
// 类定义(ES6)
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}`;
}
get info() {
return `${this.name} is ${this.age} years old`;
}
set info(value) {
[this.name, this.age] = value.split(' ');
}
}
// 创建实例
const person = new Person('Alice', 25);
console.log(person.greet());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 4.2 继承和多态
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return 'Some sound';
}
}
class Dog extends Animal {
speak() {
return 'Woof!';
}
}
class Cat extends Animal {
speak() {
return 'Meow!';
}
}
// 多态
const animals = [new Dog('Rex'), new Cat('Whiskers')];
animals.forEach(animal => console.log(animal.speak()));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 4.3 特殊方法
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return `Vector(${this.x}, ${this.y})`;
}
valueOf() {
return Math.sqrt(this.x ** 2 + this.y ** 2);
}
[Symbol.iterator]() {
return [this.x, this.y][Symbol.iterator]();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 5. 数据处理基础
# 5.1 数组操作
// 数组方法
const numbers = [1, 2, 3, 4, 5];
// 添加/删除元素
numbers.push(6); // 末尾添加
numbers.pop(); // 末尾删除
numbers.unshift(0); // 开头添加
numbers.shift(); // 开头删除
// clear
numbers.length = 0; // Method 1: Set length to 0 (most efficient)
numbers = []; // Method 2: Assign empty array
numbers.splice(0, numbers.length); // Method 3: Use splice to remove all elements
while (numbers.length > 0) { // Method 4: Use pop() in a loop (less efficient)
numbers.pop();
}
// remove: 找到元素 key 在数组中的索引位置, 从该索引位置开始,删除 1 个元素
numbers.splice(numbers.indexOf(key), 1)
// 遍历方法
numbers.forEach(num => console.log(num));
const doubled = numbers.map(num => num * 2);
const evens = numbers.filter(num => num % 2 === 0);
const sum = numbers.reduce((acc, num) => acc + num, 0);
// 查找方法
const found = numbers.find(num => num > 3);
const index = numbers.findIndex(num => num > 3);
const includes = numbers.includes(3);
// 排序和反转
numbers.sort((a, b) => a - b);
numbers.reverse();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 5.2 对象操作
// 对象方法
const person = { name: 'Alice', age: 25 };
// 获取键值
Object.keys(person); // ['name', 'age']
Object.values(person); // ['Alice', 25]
Object.entries(person); // [['name', 'Alice'], ['age', 25]]
// 合并对象
const newPerson = Object.assign({}, person, { city: 'New York' });
const merged = { ...person, city: 'New York' };
// 冻结对象
Object.freeze(person); // 不可修改
Object.seal(person); // 可修改属性值,但不能添加/删除属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 5.3 字符串处理
// 字符串方法
const text = ' Hello, World! ';
// 基本操作
text.trim(); // 去除首尾空格
text.toLowerCase(); // 转小写
text.toUpperCase(); // 转大写
text.replace('World', 'JavaScript'); // 替换
// 分割和连接
text.split(', '); // 分割字符串
['Hello', 'World'].join(' '); // 连接数组
// 模板字符串(ES6)
const name = 'Alice';
const greeting = `Hello, ${name}!`;
const multiline = `
This is a
multiline string
`;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 6. 异步编程
# 6.1 Promise
// 创建 Promise
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve('Success!');
} else {
reject('Failed!');
}
}, 1000);
});
// 使用 Promise
myPromise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log('Done'));
// Promise.all
const promises = [
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/comments')
];
Promise.all(promises)
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log(data));
// Promise.race
Promise.race([
fetch('/api/data'),
new Promise((_, reject) => setTimeout(() => reject('Timeout'), 5000))
]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 6.2 async/await
// async 函数
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error('User not found');
}
return await response.json();
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// 并行执行
async function fetchMultipleUsers(ids) {
const promises = ids.map(id => fetchUser(id));
return await Promise.all(promises);
}
// 错误处理
async function handleErrors() {
try {
const result = await riskyOperation();
return result;
} catch (error) {
console.error('Operation failed:', error);
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 7. 现代 JavaScript 特性
# 7.1 ES6+ 特性
// 解构赋值
const [a, b, ...rest] = [1, 2, 3, 4, 5];
const { name, age, ...otherProps } = person;
// 默认参数
function greet(name = 'World', greeting = 'Hello') {
return `${greeting}, ${name}!`;
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
// 展开运算符
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
const obj1 = { x: 1, y: 2 };
const obj2 = { ...obj1, z: 3 };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 7.2 高级语法
// 可选链操作符(ES2020)
const value = obj?.prop?.subProp?.method?.();
// 空值合并操作符(ES2020)
const result = value ?? defaultValue;
// 逻辑赋值操作符(ES2021)
let x = 1;
x ||= 2; // x = x || 2
x &&= 3; // x = x && 3
x ??= 4; // x = x ?? 4
// 私有类字段(ES2022)
class Counter {
#count = 0;
increment() {
this.#count++;
}
getCount() {
return this.#count;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 8. 函数式编程
# 8.1 高阶函数
// map
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
// filter
const evens = numbers.filter(x => x % 2 === 0);
// reduce
const sum = numbers.reduce((acc, x) => acc + x, 0);
// 组合函数
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const addOne = x => x + 1;
const double = x => x * 2;
const square = x => x ** 2;
const transform = compose(square, double, addOne);
console.log(transform(3)); // ((3 + 1) * 2) ^ 2 = 64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 8.2 不可变性
// 不可变数组操作
const original = [1, 2, 3];
const updated = [...original, 4]; // 添加元素
const filtered = original.filter(x => x !== 2); // 删除元素
const mapped = original.map(x => x * 2); // 修改元素
// 不可变对象操作
const original = { name: 'Alice', age: 25 };
const updated = { ...original, age: 26 }; // 修改属性
const { age, ...withoutAge } = original; // 删除属性
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 9. 错误处理和调试
# 9.1 错误处理策略
// 自定义错误类
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = 'ValidationError';
this.field = field;
}
}
// 错误边界
function withErrorBoundary(fn) {
return function(...args) {
try {
return fn.apply(this, args);
} catch (error) {
console.error('Function failed:', error);
// 可以发送错误到监控服务
return null;
}
};
}
// 异步错误处理
async function handleAsyncErrors() {
try {
const result = await riskyAsyncOperation();
return result;
} catch (error) {
if (error.name === 'NetworkError') {
// 处理网络错误
return retryOperation();
} else if (error.name === 'ValidationError') {
// 处理验证错误
return showValidationMessage(error.message);
} else {
// 处理其他错误
throw error;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 9.2 调试技巧
// 调试工具
console.log('Debug info:', variable);
console.table(arrayOfObjects);
console.group('Group name');
console.groupEnd();
console.time('Operation');
console.timeEnd('Operation');
// 条件断点
if (condition) {
debugger; // 只在条件满足时暂停
}
// 性能监控
const startTime = performance.now();
// ... 执行代码
const endTime = performance.now();
console.log(`Execution time: ${endTime - startTime}ms`);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 10. 最佳实践
# 10.1 代码规范
// ESLint 配置示例
// .eslintrc.js
module.exports = {
extends: ['eslint:recommended'],
rules: {
'no-unused-vars': 'error',
'no-console': 'warn',
'prefer-const': 'error',
'no-var': 'error'
}
};
// 代码风格
// 使用 const 和 let,避免 var
const PI = 3.14159;
let counter = 0;
// 使用箭头函数
const add = (a, b) => a + b;
// 使用模板字符串
const message = `Hello, ${name}!`;
// 使用解构赋值
const { name, age } = user;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 10.2 性能优化
// 避免重复计算
const expensive = (() => {
const result = heavyComputation();
return () => result;
})();
// 防抖和节流
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// 内存管理
class Cache {
constructor(maxSize = 100) {
this.cache = new Map();
this.maxSize = maxSize;
}
set(key, value) {
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
get(key) {
return this.cache.get(key);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 11. 实用技巧和常用函数
# 11.1 常用工具函数
// 类型检查
const isString = value => typeof value === 'string';
const isNumber = value => typeof value === 'number' && !isNaN(value);
const isArray = value => Array.isArray(value);
const isObject = value => value !== null && typeof value === 'object';
const isFunction = value => typeof value === 'function';
// 深拷贝
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime());
if (obj instanceof Array) return obj.map(item => deepClone(item));
if (typeof obj === 'object') {
const clonedObj = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
}
// 防抖函数
function debounce(func, wait, immediate = false) {
let timeout;
return function executedFunction(...args) {
const later = () => {
timeout = null;
if (!immediate) func.apply(this, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(this, args);
};
}
// 节流函数
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 11.2 数组操作技巧
// 数组去重
const unique = [...new Set(array)];
const uniqueByKey = (array, key) => {
const seen = new Set();
return array.filter(item => {
const value = item[key];
if (seen.has(value)) {
return false;
}
seen.add(value);
return true;
});
};
// 数组分组
function groupBy(array, key) {
return array.reduce((groups, item) => {
const group = item[key];
groups[group] = groups[group] || [];
groups[group].push(item);
return groups;
}, {});
}
// 数组分块
function chunk(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
// 数组扁平化
function flatten(array, depth = Infinity) {
return depth > 0
? array.reduce((acc, val) =>
acc.concat(Array.isArray(val) ? flatten(val, depth - 1) : val), [])
: array.slice();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 11.3 对象操作技巧
// 对象扁平化
function flattenObject(obj, prefix = '') {
return Object.keys(obj).reduce((acc, key) => {
const pre = prefix.length ? prefix + '.' : '';
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
Object.assign(acc, flattenObject(obj[key], pre + key));
} else {
acc[pre + key] = obj[key];
}
return acc;
}, {});
}
// 对象深合并
function deepMerge(target, source) {
const result = { ...target };
for (const key in source) {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
result[key] = deepMerge(result[key] || {}, source[key]);
} else {
result[key] = source[key];
}
}
return result;
}
// 对象属性选择
function pick(obj, keys) {
return keys.reduce((result, key) => {
if (key in obj) {
result[key] = obj[key];
}
return result;
}, {});
}
function omit(obj, keys) {
return Object.keys(obj)
.filter(key => !keys.includes(key))
.reduce((result, key) => {
result[key] = obj[key];
return result;
}, {});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 12. 学习资源
# 官方文档
# 在线教程
- JavaScript.info (opens new window)
- Eloquent JavaScript (opens new window)
- You Don't Know JS (opens new window)
# 实践项目
# 社区资源
- Stack Overflow (opens new window)
- Reddit r/javascript (opens new window)
- JavaScript Weekly (opens new window)
# 学习路径建议
# 初级阶段(1-2个月)
- 掌握 JavaScript 基础语法
- 熟悉数据类型和变量
- 学会函数定义和调用
- 理解作用域和闭包
- 完成基础项目练习
# 中级阶段(2-3个月)
- 深入学习面向对象编程
- 掌握异步编程(Promise, async/await)
- 学习 ES6+ 新特性
- 理解函数式编程概念
- 开始使用现代工具链
# 高级阶段(3-6个月)
- 学习设计模式
- 掌握性能优化技巧
- 深入理解 JavaScript 引擎
- 学习测试和调试
- 完成综合项目
# 专家阶段(6个月以上)
- 深入研究特定领域(前端框架、Node.js等)
- 参与开源项目
- 学习高级概念(微前端、WebAssembly等)
- 持续学习和实践
# 常见问题
# Q: 如何选择 JavaScript 版本?
A: 现代开发推荐使用 ES6+ 特性,通过 Babel 等工具进行转译以支持旧浏览器。
# Q: 学习 JavaScript 需要什么基础?
A: 基本的 HTML 和 CSS 知识,以及计算机操作能力即可。
# Q: 如何提高编程效率?
A: 多练习、使用现代开发工具、阅读优秀代码、参与开源项目。
# Q: 学完基础后应该学什么?
A: 根据方向选择:前端框架(React、Vue、Angular)、Node.js 后端开发、移动端开发等。
# 总结
JavaScript 是一门强大而灵活的编程语言,是现代 Web 开发的核心技术。通过系统性的学习和持续的实践,您可以掌握 JavaScript 编程技能,并在各个领域发挥其优势。
记住:编程是一门实践的艺术,多写代码、多调试、多思考,才能真正掌握 JavaScript 编程。
# 附录:常用 API 参考
# Object 方法
Object.assign(target, source): 复制所有可枚举属性到目标对象Object.keys(obj): 返回对象自身可枚举属性的键名数组Object.values(obj): 返回对象自身可枚举属性的值数组Object.entries(obj): 返回对象自身可枚举属性的键值对数组Object.freeze(obj): 冻结对象,使其不可修改Object.seal(obj): 密封对象,可修改属性值但不能添加/删除属性
# Array 方法
# 1. 数组增删操作
// push() - 在数组末尾添加一个或多个元素
const fruits = ['apple', 'banana'];
fruits.push('orange'); // 返回新长度: 3
fruits.push('grape', 'mango'); // 可以添加多个元素
console.log(fruits); // ['apple', 'banana', 'orange', 'grape', 'mango']
// pop() - 删除并返回数组的最后一个元素
const lastFruit = fruits.pop(); // 返回: 'mango'
console.log(fruits); // ['apple', 'banana', 'orange', 'grape']
// shift() - 删除并返回数组的第一个元素
const firstFruit = fruits.shift(); // 返回: 'apple'
console.log(fruits); // ['banana', 'orange', 'grape']
// unshift() - 在数组开头添加一个或多个元素
fruits.unshift('kiwi'); // 返回新长度: 4
fruits.unshift('pear', 'plum'); // 可以添加多个元素
console.log(fruits); // ['pear', 'plum', 'kiwi', 'banana', 'orange', 'grape']
// 性能对比:shift/unshift 比 push/pop 慢,因为需要移动所有元素
const largeArray = new Array(10000).fill(0);
console.time('shift');
largeArray.shift(); // 慢 - O(n)
console.timeEnd('shift');
console.time('pop');
largeArray.pop(); // 快 - O(1)
console.timeEnd('pop');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 2. 数组切片和修改
// slice(startIndex, endIndex) - 提取数组的一部分,不修改原数组
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const firstThree = numbers.slice(0, 3); // [1, 2, 3]
const lastThree = numbers.slice(-3); // [8, 9, 10]
const middle = numbers.slice(3, 7); // [4, 5, 6, 7]
const copy = numbers.slice(); // 浅拷贝整个数组
console.log(numbers); // 原数组不变: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// splice(startIndex, deleteCount, ...items) - 修改数组,删除/插入元素
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处的元素
console.log(colors); // ['red', 'orange', 'cyan', 'yellow', 'purple']
// 删除末尾元素
colors.splice(-1, 1); // 删除最后一个元素
console.log(colors); // ['red', 'orange', 'cyan', 'yellow']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 3. 函数式编程方法
// map() - 对数组中的每个元素执行函数,返回新数组
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8, 10]
const squared = numbers.map(x => x ** 2); // [1, 4, 9, 16, 25]
const formatted = numbers.map(x => `Number: ${x}`); // ['Number: 1', 'Number: 2', ...]
// 对象数组的 map 操作
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 }
];
const names = users.map(user => user.name); // ['Alice', 'Bob', 'Charlie']
const userInfo = users.map(user => ({
id: user.id,
info: `${user.name} (${user.age})`
}));
// filter() - 过滤数组元素,返回满足条件的元素
const scores = [85, 92, 78, 96, 88, 75, 90];
const highScores = scores.filter(score => score >= 90); // [92, 96, 90]
const evenScores = scores.filter(score => score % 2 === 0); // [92, 78, 96, 88, 90]
// 对象数组的 filter 操作
const activeUsers = users.filter(user => user.age < 35); // 只保留年龄小于35的用户
// reduce() - 将数组归并为单个值
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 15
const product = numbers.reduce((acc, curr) => acc * curr, 1); // 120
// 复杂 reduce 示例
const orders = [
{ product: 'apple', price: 2.5, quantity: 3 },
{ product: 'banana', price: 1.5, quantity: 2 },
{ product: 'orange', price: 3.0, quantity: 1 }
];
const totalValue = orders.reduce((total, order) => {
return total + (order.price * order.quantity);
}, 0); // 11.5
// 分组统计
const words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple'];
const wordCount = words.reduce((count, word) => {
count[word] = (count[word] || 0) + 1;
return count;
}, {}); // { apple: 3, banana: 2, cherry: 1 }
// 链式调用
const result = numbers
.filter(x => x % 2 === 0) // [2, 4]
.map(x => x * 2) // [4, 8]
.reduce((sum, x) => sum + x, 0); // 12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 4. 查找方法
// find() - 返回第一个满足条件的元素
const users = [
{ id: 1, name: 'Alice', age: 25, active: true },
{ id: 2, name: 'Bob', age: 30, active: false },
{ id: 3, name: 'Charlie', age: 35, active: true },
{ id: 4, name: 'David', age: 28, active: true }
];
const firstActive = users.find(user => user.active); // { id: 1, name: 'Alice', ... }
const youngUser = users.find(user => user.age < 30); // { id: 1, name: 'Alice', ... }
const notFound = users.find(user => user.age > 50); // undefined
// findIndex() - 返回第一个满足条件的元素索引
const activeIndex = users.findIndex(user => user.active); // 0
const oldUserIndex = users.findIndex(user => user.age > 40); // -1 (未找到)
// includes() - 检查数组是否包含指定元素
const fruits = ['apple', 'banana', 'orange'];
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('grape')); // false
// 对象数组的 includes 检查
const hasAlice = users.some(user => user.name === 'Alice'); // true
const allActive = users.every(user => user.active); // false
// 高级查找示例
const searchUsers = (query) => {
return users.filter(user =>
user.name.toLowerCase().includes(query.toLowerCase()) ||
user.id.toString().includes(query)
);
};
console.log(searchUsers('al')); // [{ id: 1, name: 'Alice', ... }]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 5. 排序和反转
// sort() - 排序数组(默认按字符串排序)
const fruits = ['banana', 'apple', 'cherry', 'date'];
fruits.sort(); // ['apple', 'banana', 'cherry', 'date']
// 数字排序
const numbers = [10, 5, 8, 1, 9, 3];
numbers.sort(); // [1, 10, 3, 5, 8, 9] - 字符串排序!
// 正确的数字排序
numbers.sort((a, b) => a - b); // 升序: [1, 3, 5, 8, 9, 10]
numbers.sort((a, b) => b - a); // 降序: [10, 9, 8, 5, 3, 1]
// 对象数组排序
const students = [
{ name: 'Alice', grade: 85 },
{ name: 'Bob', grade: 92 },
{ name: 'Charlie', grade: 78 },
{ name: 'David', grade: 96 }
];
// 按成绩排序
students.sort((a, b) => b.grade - a.grade); // 按成绩降序
// 按名字排序
students.sort((a, b) => a.name.localeCompare(b.name));
// 多条件排序
const employees = [
{ name: 'Alice', department: 'HR', salary: 50000 },
{ name: 'Bob', department: 'IT', salary: 60000 },
{ name: 'Charlie', department: 'HR', salary: 55000 },
{ name: 'David', department: 'IT', salary: 65000 }
];
// 先按部门,再按薪资排序
employees.sort((a, b) => {
if (a.department !== b.department) {
return a.department.localeCompare(b.department);
}
return b.salary - a.salary;
});
// reverse() - 反转数组
const letters = ['a', 'b', 'c', 'd'];
letters.reverse(); // ['d', 'c', 'b', 'a']
// 创建反转副本(不修改原数组)
const reversed = [...letters].reverse();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 6. 实用组合示例
// 数组去重
const duplicates = [1, 2, 2, 3, 4, 4, 5];
const unique = [...new Set(duplicates)]; // [1, 2, 3, 4, 5]
// 对象数组去重
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 1, name: 'Alice' }, // 重复
{ id: 3, name: 'Charlie' }
];
const uniqueUsers = users.filter((user, index, self) =>
index === self.findIndex(u => u.id === user.id)
);
// 数组分块
const chunk = (array, size) => {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
};
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(chunk(numbers, 3)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 数组扁平化
const nested = [1, [2, 3], [4, [5, 6]]];
const flattened = nested.flat(Infinity); // [1, 2, 3, 4, 5, 6]
// 数组交集、并集、差集
const set1 = [1, 2, 3, 4, 5];
const set2 = [4, 5, 6, 7, 8];
const intersection = set1.filter(x => set2.includes(x)); // [4, 5]
const union = [...new Set([...set1, ...set2])]; // [1, 2, 3, 4, 5, 6, 7, 8]
const difference = set1.filter(x => !set2.includes(x)); // [1, 2, 3]
// 数组统计
const grades = [85, 92, 78, 96, 88, 75, 90];
const stats = {
count: grades.length,
sum: grades.reduce((a, b) => a + b, 0),
average: grades.reduce((a, b) => a + b, 0) / grades.length,
min: Math.min(...grades),
max: Math.max(...grades),
range: Math.max(...grades) - Math.min(...grades)
};
// 数组分组
const groupBy = (array, key) => {
return array.reduce((groups, item) => {
const group = item[key];
groups[group] = groups[group] || [];
groups[group].push(item);
return groups;
}, {});
};
const products = [
{ name: 'Apple', category: 'Fruit', price: 2.5 },
{ name: 'Banana', category: 'Fruit', price: 1.5 },
{ name: 'Carrot', category: 'Vegetable', price: 1.0 },
{ name: 'Broccoli', category: 'Vegetable', price: 2.0 }
];
const grouped = groupBy(products, 'category');
// {
// Fruit: [{ name: 'Apple', ... }, { name: 'Banana', ... }],
// Vegetable: [{ name: 'Carrot', ... }, { name: 'Broccoli', ... }]
// }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 7. 性能优化技巧
// 避免在循环中修改数组长度
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 错误方式 - 可能导致无限循环
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
numbers.splice(i, 1); // 修改数组长度
i--; // 需要调整索引
}
}
// 正确方式 - 从后往前遍历
for (let i = numbers.length - 1; i >= 0; i--) {
if (numbers[i] % 2 === 0) {
numbers.splice(i, 1);
}
}
// 更好的方式 - 使用 filter
const oddNumbers = numbers.filter(n => n % 2 !== 0);
// 大数组操作优化
const largeArray = new Array(100000).fill(0).map((_, i) => i);
// 使用 for...of 替代 forEach(性能更好)
console.time('forEach');
largeArray.forEach(x => x * 2);
console.timeEnd('forEach');
console.time('for...of');
for (const x of largeArray) {
x * 2;
}
console.timeEnd('for...of');
// 使用 Set 进行快速查找
const searchArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const searchSet = new Set(searchArray);
console.time('array includes');
searchArray.includes(5);
console.timeEnd('array includes');
console.time('set has');
searchSet.has(5);
console.timeEnd('set has');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
上次更新: 2025/10/10, 14:12:02