文章目录
-
-
-
- [1. 引言](#1. 引言)
-
- [2. 核心概念与语法基础](#2. 核心概念与语法基础)
-
- [3. 函数与异步编程](#3. 函数与异步编程)
-
- [4. 内置对象与DOM操作](#4. 内置对象与DOM操作)
-
- 内置对象
- [HTML DOM 操作](#HTML DOM 操作)
- [5. 面向对象编程 (OOP)](#5. 面向对象编程 (OOP))
-
- [6. 性能优化与工具](#6. 性能优化与工具)
-
- [7. 测试与部署](#7. 测试与部署)
-
- [8. 实践](#8. 实践)
-
1. 引言
起源与发展
- LiveScript到JavaScript:1995年,Netscape的Brendan Eich在短短十天内开发了LiveScript,后来更名为JavaScript。
- 标准化历程 :
- ECMAScript (ES):由ECMA International组织定义的标准规范。
- 版本更新:如ES6/ES2015引入了许多新特性,包括箭头函数、模板字符串、解构赋值、类(class)等。
- 未来趋势:每年发布的新版本继续扩展语言功能,如模块化、异步迭代器等。
应用领域
- 浏览器端脚本:最初用于增强网页交互性。
- 服务器端编程:Node.js使得JavaScript可以在服务器端运行,构建后端服务。
- 移动与桌面应用:React Native, Electron等框架允许使用JavaScript开发跨平台的应用程序。
- 物联网:JavaScript也被应用于智能家居设备和其他嵌入式系统中。
2. 核心概念与语法基础
动态类型语言
- 特点与挑战 :
- 灵活性:无需声明变量类型,简化了代码编写。
- 潜在问题:容易引发运行时错误,建议结合静态类型检查工具(如TypeScript)使用。
- 最佳实践:始终初始化变量,避免未定义的行为;使用严格模式("use strict")减少意外行为。
javascript
复制代码
// 使用严格模式
'use strict';
let message = 'Hello World!';
console.log(message);
基于原型的继承
- 原型链机制 :每个对象都有一个内部属性
[[Prototype]]
指向其原型对象。
- 构造函数 :通过
new
关键字创建实例,并将实例的[[Prototype]]
设置为构造函数的prototype
属性。
- 原型继承 vs 类继承:虽然ES6引入了类(class),但JavaScript本质上仍然是基于原型的。类只是对原型继承的一种更直观的表达方式。
javascript
复制代码
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person1 = new Person('Alice');
person1.greet(); // 输出: Hello, my name is Alice
事件驱动与非阻塞异步
- 事件循环:JavaScript采用单线程模型,通过事件循环处理任务队列中的异步操作。
- 微任务与宏任务:理解Promise和setTimeout的区别,以及它们在事件循环中的执行顺序。
- 性能优势:提高响应性能,避免阻塞用户界面,确保程序流畅运行。
javascript
复制代码
console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('End');
// 输出顺序: Start, End, Promise, Timeout
闭包 (Closures)
- 定义与应用场景 :
- 私有变量:通过闭包实现数据封装,防止外部直接访问。
- 模拟块级作用域:在ES6之前,闭包是唯一的方式。
- 工厂模式:返回一个包含状态和方法的对象。
- 内存管理:闭包可能会导致内存泄漏,因为它们保持对外部变量的引用。需谨慎使用,尤其是在长时间运行的应用中。
javascript
复制代码
function createCounter() {
let count = 0; // 私有变量
return function() {
count += 1;
return count;
}
}
const counter = createCounter();
console.log(counter()); // 输出: 1
console.log(counter()); // 输出: 2
this
关键字
- 调用方式与绑定问题 :
- 简单调用 :
this
指向全局对象或undefined
(严格模式下)。
- 方法调用 :
this
指向调用该方法的对象。
- 构造器调用 :
this
指向新创建的实例。
- apply/call/bind 调用 :
this
指向第一个参数指定的对象。
- 解决方案 :使用箭头函数自动绑定外层
this
,或者显式绑定上下文以避免混淆。
javascript
复制代码
const obj = {
value: 42,
getValue: function() {
return this.value;
}
};
console.log(obj.getValue()); // 输出: 42
const boundGetValue = obj.getValue.bind({ value: 84 });
console.log(boundGetValue()); // 输出: 84
基本语法
- 注释:单行(//)和多行(/* */)注释的用法。
- 严格模式:"use strict"; 的作用及启用更严格的解析规则,减少错误发生。
- 声明与表达式:语句和表达式的区别及其在代码中的运用,包括函数声明与函数表达式的不同。
- 变量与数据类型 :
- let, const, var :
var
有函数作用域,let
和const
有块级作用域,const
用于声明不可再赋值的常量。
- 基本数据类型:Number, String, Boolean, null, undefined, Symbol, BigInt。
javascript
复制代码
// 变量声明
let x = 10;
const PI = 3.14;
if (true) {
let y = 20; // 块级作用域
console.log(y); // 输出: 20
}
// console.log(y); // 报错: y is not defined
- 运算符 :
- 算术运算符:+、-、*、/、%等。
- 赋值运算符:=、+=、-=、*=、/=等。
- 比较运算符 :、=、!=、!==、>、<等。
- 逻辑运算符:&&、||、!。
- 条件运算符 :三元运算符
? :
。
- 位运算符:&、|、^、~、<<、>>、>>>。
- 解构赋值:从数组或对象中提取值并赋给变量。
javascript
复制代码
// 解构赋值
const [a, b] = [1, 2];
console.log(a, b); // 输出: 1 2
const { name, age } = { name: 'Alice', age: 25 };
console.log(name, age); // 输出: Alice 25
- 控制语句 :
- 条件结构:if、else、switch-case,三元运算符。
- 循环结构:for、while、do-while、for...in、for...of,迭代器和生成器。
- 异常处理:try...catch...finally,throw语句,Error对象。
javascript
复制代码
// 条件结构
if (x > 0) {
console.log('Positive');
} else if (x < 0) {
console.log('Negative');
} else {
console.log('Zero');
}
// 循环结构
for (let i = 0; i < 5; i++) {
console.log(i);
}
// 异常处理
try {
throw new Error('An error occurred');
} catch (e) {
console.error(e.message);
} finally {
console.log('Finally block');
}
3. 函数与异步编程
定义与调用
- 普通函数:传统的函数定义方式。
- 箭头函数 :ES6引入的新语法糖,简化了函数定义,并有其独特的
this
绑定行为。
- 匿名函数与IIFE:立即执行函数表达式,用于创建局部作用域或初始化配置。
- 高阶函数:接受其他函数作为参数或返回函数的函数,增强了代码的抽象层次。
- 回调函数:作为参数传递给另一个函数,在特定条件下执行。
javascript
复制代码
// 箭头函数
const add = (a, b) => a + b;
console.log(add(2, 3)); // 输出: 5
// IIFE
(function() {
console.log('This runs immediately');
})();
参数特性
- 默认参数:为函数参数设置默认值,使函数调用更加灵活。
- 剩余参数与扩展运算符:收集不定数量的参数或展开数组/对象。
- 参数解构:直接从对象或数组中提取值并赋给变量,简化了参数传递。
- 命名参数:通过对象字面量传递参数,提高可读性和灵活性。
javascript
复制代码
// 默认参数
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // 输出: Hello, Guest
greet('Alice'); // 输出: Hello, Alice
// 剩余参数
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 输出: 10
// 参数解构
function introduce({ name, age }) {
console.log(`${name} is ${age} years old`);
}
introduce({ name: 'Bob', age: 30 }); // 输出: Bob is 30 years old
闭包与作用域
- 理解变量的作用范围:全局作用域、函数作用域、块级作用域(ES6新增)。
- 提升变量(Hoisting):变量声明会被"提升"到其所在作用域的顶部,但初始化不会。
- 词法作用域 vs 动态作用域:JavaScript采用词法作用域,即作用域在编译阶段确定,不受运行时影响。
javascript
复制代码
// 词法作用域
function outer() {
let x = 10;
function inner() {
console.log(x); // 访问外层函数的变量
}
inner();
}
outer(); // 输出: 10
异步编程
- Promise :表示一个异步操作的最终完成(或失败)及其结果值。提供了
.then()
、.catch()
和 .finally()
方法来处理成功和失败的情况。
- Async/Await:基于Promise的语法糖,使异步代码看起来像同步代码,从而简化了异步逻辑的编写。
- 解决回调地狱:通过Promises和async/await,避免嵌套过多的回调函数,提高了代码的可读性和维护性。
- 并发控制 :使用
Promise.all()
、Promise.race()
等方法同时处理多个异步操作。
javascript
复制代码
// Promise
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('Done!'), 1000);
});
promise.then(result => console.log(result)); // 1秒后输出: Done!
// Async/Await
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
4. 内置对象与DOM操作
内置对象
- String, Array, Date, Math, JSON, RegExp:常用内置对象的方法和属性。
- 数组的迭代方法:forEach, map, filter, reduce等,增强数据处理能力。
- 正则表达式:RegExp对象用于匹配和替换文本,支持复杂的模式匹配。
javascript
复制代码
// 数组的迭代方法
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // 输出: [2, 4, 6, 8, 10]
// 正则表达式
const text = 'The quick brown fox jumps over the lazy dog';
const regex = /fox/;
console.log(regex.test(text)); // 输出: true
HTML DOM 操作
- 查找元素:getElementById, getElementsByClassName, querySelector, querySelectorAll等方法。
- 修改内容与样式:innerHTML, textContent, classList, style属性的应用,setAttribute(), removeAttribute()。
- 节点操作:创建(createElement, createTextNode)、删除(removeChild)、插入(appendChild, insertBefore)、复制(cloneNode)节点。
- 事件绑定与解绑:为DOM元素添加或移除事件处理器,事件代理技术。
- 常见事件类型:鼠标事件、键盘事件、表单事件、触摸事件等。
- 动画与过渡:CSS动画与JavaScript结合,创建流畅的用户界面效果。
javascript
复制代码
// 查找元素
const element = document.querySelector('#my-element');
element.textContent = 'New content';
// 事件绑定
element.addEventListener('click', () => {
console.log('Element clicked');
});
5. 面向对象编程 (OOP)
类与继承
- ES6类:引入了类(class)的概念,简化了面向对象编程的方式。虽然JavaScript本质上是基于原型的,但类提供了一种更直观的方式来组织代码。
- 继承 :子类可以通过
extends
关键字继承父类的属性和方法,同时可以重写或扩展这些成员。
- 构造函数 :使用
constructor
定义类的初始化逻辑。
- 静态方法 :通过
static
关键字定义类级别的方法,不需要实例化即可调用。
- getter/setter:在类中定义getter和setter方法来控制对属性的访问和修改,保证数据的有效性和安全性。
javascript
复制代码
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog('Rex');
d.speak(); // 输出: Rex barks.
// Getter/Setter
class Person {
constructor(age) {
this._age = age;
}
get age() {
return this._age;
}
set age(value) {
if (value < 0) {
throw new Error('Age cannot be negative.');
}
this._age = value;
}
}
const person = new Person(25);
console.log(person.age); // 输出: 25
person.age = 30;
console.log(person.age); // 输出: 30
封装与模块化
- 模块化编程:ES6模块系统,import/export语句,CommonJS与AMD规范对比。
- 命名空间:通过对象或立即执行函数表达式(IIFE)创建命名空间,避免全局污染。
- 依赖管理:使用Webpack、Rollup等工具进行依赖管理和打包优化。
javascript
复制代码
// 模块化编程
export function add(a, b) {
return a + b;
}
// 在另一个文件中导入
import { add } from './math';
console.log(add(2, 3)); // 输出: 5
6. 性能优化与工具
减少重绘与回流
- 优化渲染:通过批量更新DOM、避免不必要的样式计算等方式,减少重绘(repaint)和回流(reflow)操作的数量,提高页面加载速度和用户体验。
- 虚拟DOM:React等框架利用虚拟DOM减少直接操作真实DOM的次数,提升性能。
javascript
复制代码
// 批量更新DOM
document.body.style.color = 'red';
document.body.style.backgroundColor = 'blue';
// 更优的做法是合并样式更改
document.body.style.cssText = 'color: red; background-color: blue;';
代码分割与懒加载
- 按需加载:通过将应用拆分为多个小模块,并仅在需要时加载它们,显著提高首屏加载速度。Webpack等构建工具提供了动态导入功能来支持这一点。
- 代码分割策略:根据路由、组件、懒加载等场景进行合理的代码分割。
javascript
复制代码
// 动态导入
button.addEventListener('click', async () => {
const module = await import('./module.js');
module.someFunction();
});
使用服务端渲染 (SSR)
- 加快首屏显示:对于SPA(单页应用),初始加载可能较慢,因为必须等待所有JavaScript下载并执行完毕才能呈现内容。使用SSR可以在服务器上预先渲染页面,加快首屏显示时间。
- SEO优化:SSR生成的HTML有助于搜索引擎爬虫更好地索引页面内容。
javascript
复制代码
// SSR 示例(简化)
app.get('/', async (req, res) => {
const appHtml = ReactDOMServer.renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<body>
<div id="root">${appHtml}</div>
<script src="/bundle.js"></script>
</body>
</html>
`);
});
构建工具
- 打包工具:Webpack, Rollup, Parcel等打包工具的配置与使用,帮助开发者管理和优化前端资源。
- 前端框架:React, Vue, Angular等流行框架的特点与适用场景,选择最适合项目需求的技术栈。
- 环境配置:配置不同的开发、测试和生产环境,确保代码稳定性和安全性。
javascript
复制代码
// Webpack 配置示例
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
}
};
7. 测试与部署
单元测试与集成测试
- 自动化测试:编写单元测试确保每个组件按预期工作,而集成测试则验证不同部分之间的交互是否正确。Jest、Mocha等框架可以帮助自动化测试过程。
- TDD/BDD开发模式:测试驱动开发(Test-Driven Development)和行为驱动开发(Behavior-Driven Development)鼓励先写测试再写实现代码,提高代码质量和可靠性。
- 测试覆盖率:通过工具(如Istanbul)分析测试覆盖率,确保关键路径得到充分测试。
javascript
复制代码
// Jest 单元测试示例
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
持续集成/持续部署 (CI/CD)
- 自动化流程:使用GitHub Actions、GitLab CI等工具设置自动化构建、测试和部署流程,保证代码质量并加快发布周期。
- 部署策略:蓝绿部署、滚动更新等策略确保新版本上线平滑过渡,减少停机时间和风险。
yaml
复制代码
# GitHub Actions 示例
name: CI
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Build project
run: npm run build
8. 实践
代码风格要求
- 一致性:遵循一致的代码风格有助于提高代码的可读性和维护性,如Airbnb或Google提供的JavaScript风格指南。
- 命名约定:采用有意义且统一的变量名和函数名,提高代码的可理解性。
- 注释与文档:为复杂逻辑添加适当的注释,使用JSDoc生成API文档。
javascript
复制代码
// Airbnb 风格指南示例
const helloWorld = () => {
return 'Hello, world!';
};
版本
- Git/GitHub:掌握Git的基础命令和GitHub的操作,如克隆仓库、提交更改、创建分支、合并代码等。
- 协作开发流程:了解如何有效地进行团队合作,包括代码审查、问题跟踪和持续集成。
- 分支管理策略:如Git Flow、GitHub Flow等,确保代码库的整洁和有序。
bash
复制代码
# Git 基础命令
git clone https://github.com/user/repo.git
git checkout -b feature/new-feature
git add .
git commit -m "Add new feature"
git push origin feature/new-feature