JavaScript
目录
基础语法
变量声明
javascript
// ES6+ 变量声明
let name = 'John'; // 可重新赋值
const age = 25; // 不可重新赋值
var old = true; // 旧式声明,不推荐使用
// 变量提升
console.log(hoisted); // undefined
var hoisted = 'I am hoisted';
// 暂时性死区
console.log(temporalDeadZone); // ReferenceError
let temporalDeadZone = 'I am not hoisted';说明:
let和const是块级作用域var是函数作用域,存在变量提升const声明的是引用不可变,但对象内容可变- 使用
let和const可以避免变量提升带来的问题
数据类型
javascript
// 基本类型
const str = 'string'; // 字符串
const num = 123; // 数字
const bool = true; // 布尔值
const nul = null; // 空值
const undef = undefined; // 未定义
const sym = Symbol('unique'); // 符号
// 引用类型
const obj = { name: 'John' }; // 对象
const arr = [1, 2, 3]; // 数组
const func = () => {}; // 函数
// 类型检查
console.log(typeof str); // 'string'
console.log(typeof num); // 'number'
console.log(typeof bool); // 'boolean'
console.log(typeof nul); // 'object'
console.log(typeof undef); // 'undefined'
console.log(typeof sym); // 'symbol'
console.log(typeof obj); // 'object'
console.log(typeof arr); // 'object'
console.log(typeof func); // 'function'
// 类型转换
const numStr = '123';
console.log(Number(numStr)); // 123
console.log(String(123)); // '123'
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean('')); // false
console.log(Boolean('hello')); // true说明:
- JavaScript 有 7 种基本类型和 1 种引用类型
- 基本类型存储在栈内存中
- 引用类型存储在堆内存中
- 使用
typeof可以检查基本类型 - 使用
instanceof可以检查引用类型 - 类型转换需要注意隐式转换的规则
运算符
javascript
// 算术运算符
const sum = 1 + 2; // 加法
const diff = 5 - 3; // 减法
const product = 2 * 3; // 乘法
const quotient = 6 / 2; // 除法
const remainder = 5 % 2; // 取余
const power = 2 ** 3; // 幂运算
// 比较运算符
const isEqual = 1 === 1; // 严格相等
const isNotEqual = 1 !== 2; // 严格不相等
const isGreater = 2 > 1; // 大于
const isLess = 1 < 2; // 小于
const isGreaterEqual = 2 >= 2; // 大于等于
const isLessEqual = 1 <= 2; // 小于等于
// 逻辑运算符
const and = true && false; // 逻辑与
const or = true || false; // 逻辑或
const not = !true; // 逻辑非
// 位运算符
const bitAnd = 5 & 3; // 按位与
const bitOr = 5 | 3; // 按位或
const bitXor = 5 ^ 3; // 按位异或
const bitNot = ~5; // 按位非
const leftShift = 5 << 1; // 左移
const rightShift = 5 >> 1; // 右移
const zeroFillRightShift = 5 >>> 1; // 无符号右移
// 赋值运算符
let x = 1;
x += 2; // x = x + 2
x -= 1; // x = x - 1
x *= 2; // x = x * 2
x /= 2; // x = x / 2
x %= 2; // x = x % 2
x **= 2; // x = x ** 2说明:
- 算术运算符用于数学计算
- 比较运算符返回布尔值
- 逻辑运算符用于条件判断
- 位运算符用于二进制操作
- 赋值运算符用于变量赋值
函数
函数声明
javascript
// 函数声明
function add(a, b) {
return a + b;
}
// 函数表达式
const subtract = function(a, b) {
return a - b;
};
// 箭头函数
const multiply = (a, b) => a * b;
// 立即执行函数
(function() {
console.log('IIFE');
})();
// 函数参数
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
// 参数解构
function printUser({ name, age }) {
console.log(`${name} is ${age} years old`);
}说明:
- 函数声明会被提升
- 函数表达式不会被提升
- 箭头函数没有自己的
this - 立即执行函数可以创建独立作用域
- 函数参数可以有默认值
- 剩余参数可以接收任意数量的参数
- 参数解构可以方便地获取对象属性
闭包
javascript
// 基本闭包
function createCounter() {
let count = 0;
return {
increment() {
count++;
return count;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.getCount()); // 1
// 模块模式
const module = (function() {
let privateVar = 'private';
function privateMethod() {
console.log(privateVar);
}
return {
publicMethod() {
privateMethod();
}
};
})();
// 柯里化
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
}
return function(...moreArgs) {
return curried.apply(this, args.concat(moreArgs));
};
};
}
const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6说明:
- 闭包可以访问外部函数的作用域
- 闭包可以创建私有变量和方法
- 闭包可以用于模块化开发
- 闭包可以用于函数式编程
- 闭包需要注意内存泄漏问题
高阶函数
javascript
// 函数作为参数
function map(arr, fn) {
const result = [];
for (let i = 0; i < arr.length; i++) {
result.push(fn(arr[i]));
}
return result;
}
const numbers = [1, 2, 3];
const doubled = map(numbers, x => x * 2);
console.log(doubled); // [2, 4, 6]
// 函数作为返回值
function multiply(x) {
return function(y) {
return x * y;
};
}
const multiplyByTwo = multiply(2);
console.log(multiplyByTwo(3)); // 6
// 函数组合
function compose(...fns) {
return function(x) {
return fns.reduceRight((y, f) => f(y), x);
};
}
const addOne = x => x + 1;
const double = x => x * 2;
const addOneAndDouble = compose(double, addOne);
console.log(addOneAndDouble(3)); // 8说明:
- 高阶函数可以接收函数作为参数
- 高阶函数可以返回函数
- 高阶函数可以用于函数组合
- 高阶函数可以用于函数式编程
- 高阶函数可以提高代码复用性
异步编程
Promise
javascript
// 基本用法
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data fetched');
}, 1000);
});
};
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
// Promise 链
fetchData()
.then(data => data.toUpperCase())
.then(data => console.log(data))
.catch(error => console.error(error));
// Promise.all
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3])
.then(values => console.log(values)) // [1, 2, 3]
.catch(error => console.error(error));
// Promise.race
Promise.race([promise1, promise2, promise3])
.then(value => console.log(value)) // 1
.catch(error => console.error(error));说明:
- Promise 用于处理异步操作
- Promise 有三种状态:pending、fulfilled、rejected
- Promise 可以链式调用
- Promise.all 等待所有 Promise 完成
- Promise.race 返回第一个完成的 Promise
Async/Await
javascript
// 基本用法
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
}
// 并行请求
async function getMultipleData() {
try {
const [data1, data2] = await Promise.all([
fetchData(),
fetchData()
]);
console.log(data1, data2);
} catch (error) {
console.error(error);
}
}
// 错误处理
async function handleErrors() {
try {
const data = await fetchData();
return data;
} catch (error) {
console.error('Error:', error);
throw error;
} finally {
console.log('Cleanup');
}
}说明:
- async/await 是 Promise 的语法糖
- async 函数总是返回 Promise
- await 只能在 async 函数中使用
- try/catch 可以处理异步错误
- finally 块总是会执行
ES6+ 特性
解构赋值
javascript
// 对象解构
const person = { name: 'John', age: 25 };
const { name, age } = person;
console.log(name, age); // John 25
// 数组解构
const numbers = [1, 2, 3];
const [first, second] = numbers;
console.log(first, second); // 1 2
// 嵌套解构
const user = {
name: 'John',
address: {
city: 'New York',
country: 'USA'
}
};
const { name, address: { city } } = user;
console.log(name, city); // John New York
// 默认值
const { name = 'Guest', age = 0 } = {};
console.log(name, age); // Guest 0说明:
- 解构赋值可以简化代码
- 可以解构对象和数组
- 支持嵌套解构
- 可以设置默认值
- 可以用于函数参数
展开运算符
javascript
// 数组展开
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
// 对象展开
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 2 }
// 函数参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6
// 复制对象
const original = { a: 1, b: 2 };
const copy = { ...original };
console.log(copy); // { a: 1, b: 2 }说明:
- 展开运算符可以展开数组和对象
- 可以用于合并数组和对象
- 可以用于函数参数
- 可以用于复制对象
- 可以用于创建新对象
类
javascript
// 基本类
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
// 继承
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
console.log(`${this.name} is studying`);
}
}
// 静态方法
class MathUtils {
static add(a, b) {
return a + b;
}
}
// 私有字段
class BankAccount {
#balance = 0;
deposit(amount) {
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}说明:
- 类是对象的模板
- 类可以继承
- 类有构造函数
- 类有方法
- 类有静态方法
- 类有私有字段
最佳实践
1. 代码风格
- 使用 ESLint
- 遵循 Airbnb 风格指南
- 使用 Prettier 格式化
- 添加适当的注释
- 使用有意义的变量名
- 保持代码简洁
2. 性能优化
- 避免全局变量
- 使用事件委托
- 合理使用闭包
- 避免内存泄漏
- 使用防抖和节流
- 优化循环和递归
3. 错误处理
- 使用 try-catch
- 合理使用 Promise
- 添加错误边界
- 记录错误日志
- 优雅降级
- 用户友好的错误提示
4. 测试
- 单元测试
- 集成测试
- 端到端测试
- 测试覆盖率
- 自动化测试
- 持续集成
学习资源
在线教程
视频课程
- 慕课网
- 极客时间
- B站技术区
- YouTube 技术频道
- Udemy
- Coursera