04. JavaScript核心原理和ES6+
📋 目录
JavaScript引擎原理
理解JavaScript 引擎的工作原理是掌握JavaScript的关键,它帮助我们写出更高效的代码。
V8引擎架构
V8 是Google Chrome 和Node.js 使用的JavaScript引擎。
// JavaScript代码执行过程
/*
1. 词法分析(Lexical Analysis)
- 将源代码分解为tokens
2. 语法分析(Syntax Analysis)
- 将tokens转换为抽象语法树(AST)
3. 字节码生成
- 将AST转换为字节码
4. 执行
- 解释器执行字节码
- 优化编译器(TurboFan)优化热点代码
*/
// 示例:变量提升的原理
console.log(a); // undefined(不是报错)
var a = 5;
// 实际执行过程:
// 1. 编译阶段:var a; (声明提升)
// 2. 执行阶段:console.log(a); a = 5;
// 函数提升
console.log(foo()); // "Hello"
function foo() {
return "Hello";
}
// let/const的暂时性死区
console.log(b); // ReferenceError
let b = 10;
内存管理和垃圾回收
// 内存分配示例
function createObjects() {
// 栈内存:存储基本类型和引用
let num = 42;
let str = "Hello";
// 堆内存:存储对象
let obj = {
name: "JavaScript",
version: "ES2024"
};
// 闭包会保持对外部变量的引用
function closure() {
return obj.name; // obj不会被垃圾回收
}
return closure;
}
// 垃圾回收机制
/*
1. 标记清除(Mark and Sweep)- 主要算法
- 标记阶段:从根对象开始,标记所有可达对象
- 清除阶段:清除未标记的对象
2. 引用计数(Reference Counting)- 辅助算法
- 跟踪每个对象的引用次数
- 引用次数为0时立即回收
- 问题:循环引用
*/
// 避免内存泄漏的最佳实践
class MemoryManager {
constructor() {
this.listeners = new Map();
this.timers = new Set();
}
// 正确管理事件监听器
addEventListener(element, event, handler) {
element.addEventListener(event, handler);
if (!this.listeners.has(element)) {
this.listeners.set(element, new Map());
}
this.listeners.get(element).set(event, handler);
}
// 清理事件监听器
removeEventListener(element, event) {
if (this.listeners.has(element)) {
const elementListeners = this.listeners.get(element);
const handler = elementListeners.get(event);
if (handler) {
element.removeEventListener(event, handler);
elementListeners.delete(event);
}
}
}
// 管理定时器
setTimeout(callback, delay) {
const timerId = setTimeout(() => {
callback();
this.timers.delete(timerId);
}, delay);
this.timers.add(timerId);
return timerId;
}
// 清理所有资源
cleanup() {
// 清理事件监听器
for (const [element, events] of this.listeners) {
for (const [event, handler] of events) {
element.removeEventListener(event, handler);
}
}
this.listeners.clear();
// 清理定时器
for (const timerId of this.timers) {
clearTimeout(timerId);
}
this.timers.clear();
}
}
执行上下文和作用域
执行上下文详解
⚠️
执行上下文是JavaScript代码执行的环境,理解它对于掌握this绑定、变量提升等概念至关重要。
// 执行上下文的组成
/*
1. 变量对象(Variable Object)/ 词法环境(Lexical Environment)
2. 作用域链(Scope Chain)
3. this绑定
*/
// 全局执行上下文
var globalVar = "global";
function outerFunction(x) {
// 函数执行上下文
var outerVar = "outer";
function innerFunction(y) {
// 内部函数执行上下文
var innerVar = "inner";
// 作用域链:innerFunction -> outerFunction -> global
console.log(innerVar); // "inner"
console.log(outerVar); // "outer"
console.log(globalVar); // "global"
console.log(x, y); // 参数也在作用域链中
}
return innerFunction;
}
const inner = outerFunction("param");
inner("arg");
// 词法作用域 vs 动态作用域
function lexicalScope() {
var name = "lexical";
function inner() {
console.log(name); // 词法作用域:在定义时确定
}
return inner;
}
function dynamicScope() {
var name = "dynamic";
lexicalScope()(); // 仍然输出 "lexical"
}
dynamicScope();
this绑定规则
// this绑定的四种规则
// 1. 默认绑定
function defaultBinding() {
console.log(this); // 严格模式下是undefined,非严格模式下是window
}
// 2. 隐式绑定
const obj = {
name: "Object",
greet() {
console.log(this.name); // "Object"
}
};
obj.greet(); // 隐式绑定
const greetFunc = obj.greet;
greetFunc(); // 默认绑定,this丢失
// 3. 显式绑定
function explicitBinding() {
console.log(this.name);
}
const context = { name: "Explicit" };
explicitBinding.call(context); // "Explicit"
explicitBinding.apply(context); // "Explicit"
const boundFunction = explicitBinding.bind(context);
boundFunction(); // "Explicit"
// 4. new绑定
function Constructor(name) {
this.name = name;
this.greet = function() {
console.log(`Hello, ${this.name}`);
};
}
const instance = new Constructor("Instance");
instance.greet(); // "Hello, Instance"
// 箭头函数的this
const arrowObj = {
name: "Arrow",
regularFunction() {
console.log(this.name); // "Arrow"
const arrowFunction = () => {
console.log(this.name); // "Arrow" - 继承外层this
};
arrowFunction();
}
};
arrowObj.regularFunction();
// 实际应用:解决this丢失问题
class EventHandler {
constructor(name) {
this.name = name;
}
// 方法1:箭头函数
handleClick = (event) => {
console.log(`${this.name} clicked`);
}
// 方法2:bind绑定
handleSubmit(event) {
console.log(`${this.name} submitted`);
}
init() {
const button = document.querySelector('#button');
const form = document.querySelector('#form');
button.addEventListener('click', this.handleClick); // 正确
form.addEventListener('submit', this.handleSubmit.bind(this)); // 正确
}
}
原型链和继承
原型链机制
// 原型链的基本概念
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return `Hello, I'm ${this.name}`;
};
const person = new Person("Alice");
// 原型链查找过程
console.log(person.greet()); // 在Person.prototype上找到
console.log(person.toString()); // 在Object.prototype上找到
// 原型链:person -> Person.prototype -> Object.prototype -> null
// 手动实现new操作符
function myNew(constructor, ...args) {
// 1. 创建新对象,原型指向构造函数的prototype
const obj = Object.create(constructor.prototype);
// 2. 执行构造函数,this指向新对象
const result = constructor.apply(obj, args);
// 3. 如果构造函数返回对象,则返回该对象,否则返回新对象
return result instanceof Object ? result : obj;
}
const person2 = myNew(Person, "Bob");
console.log(person2.greet()); // "Hello, I'm Bob"
// 原型链继承的实现
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
function Dog(name, breed) {
// 调用父构造函数
Animal.call(this, name);
this.breed = breed;
}
// 设置原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 添加子类方法
Dog.prototype.bark = function() {
return `${this.name} barks`;
};
const dog = new Dog("Buddy", "Golden Retriever");
console.log(dog.speak()); // "Buddy makes a sound"
console.log(dog.bark()); // "Buddy barks"
ES6类和继承
// ES6类语法
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound`;
}
// 静态方法
static getSpecies() {
return "Unknown";
}
// 私有字段(ES2022)
#privateField = "private";
// 私有方法
#privateMethod() {
return this.#privateField;
}
// 公共方法访问私有成员
getPrivateData() {
return this.#privateMethod();
}
}
// 继承
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类构造函数
this.breed = breed;
}
speak() {
return `${super.speak()} - Woof!`; // 调用父类方法
}
bark() {
return `${this.name} barks`;
}
static getSpecies() {
return "Canis lupus";
}
}
const dog = new Dog("Max", "Labrador");
console.log(dog.speak()); // "Max makes a sound - Woof!"
console.log(Dog.getSpecies()); // "Canis lupus"
// Mixin模式
const Flyable = {
fly() {
return `${this.name} is flying`;
}
};
const Swimmable = {
swim() {
return `${this.name} is swimming`;
}
};
// 组合多个能力
class Duck extends Animal {
constructor(name) {
super(name);
}
}
// 添加mixin
Object.assign(Duck.prototype, Flyable, Swimmable);
const duck = new Duck("Donald");
console.log(duck.fly()); // "Donald is flying"
console.log(duck.swim()); // "Donald is swimming"
异步编程深入
Promise原理和实现
Promise是JavaScript异步编程的核心,理解其原理有助于更好地处理异步操作。
// 手动实现Promise
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback());
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(callback => callback());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };
return new MyPromise((resolve, reject) => {
const handleFulfilled = () => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
};
const handleRejected = () => {
try {
const result = onRejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
};
if (this.state === 'fulfilled') {
setTimeout(handleFulfilled, 0);
} else if (this.state === 'rejected') {
setTimeout(handleRejected, 0);
} else {
this.onFulfilledCallbacks.push(handleFulfilled);
this.onRejectedCallbacks.push(handleRejected);
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(onFinally) {
return this.then(
value => MyPromise.resolve(onFinally()).then(() => value),
reason => MyPromise.resolve(onFinally()).then(() => { throw reason; })
);
}
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason));
}
static all(promises) {
return new MyPromise((resolve, reject) => {
const results = [];
let completedCount = 0;
promises.forEach((promise, index) => {
MyPromise.resolve(promise).then(
value => {
results[index] = value;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
},
reject
);
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
MyPromise.resolve(promise).then(resolve, reject);
});
});
}
}
// 使用示例
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => resolve("Success!"), 1000);
});
promise
.then(value => {
console.log(value); // "Success!"
return value.toUpperCase();
})
.then(value => {
console.log(value); // "SUCCESS!"
})
.catch(error => {
console.error(error);
});
async/await深入
// async/await的本质是Promise的语法糖
async function asyncFunction() {
try {
const result1 = await fetch('/api/data1');
const data1 = await result1.json();
const result2 = await fetch(`/api/data2/${data1.id}`);
const data2 = await result2.json();
return { data1, data2 };
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// 等价的Promise写法
function promiseFunction() {
return fetch('/api/data1')
.then(result1 => result1.json())
.then(data1 => {
return fetch(`/api/data2/${data1.id}`)
.then(result2 => result2.json())
.then(data2 => ({ data1, data2 }));
})
.catch(error => {
console.error('Error:', error);
throw error;
});
}
// 并发处理
async function concurrentRequests() {
try {
// 串行执行(慢)
const data1 = await fetch('/api/data1');
const data2 = await fetch('/api/data2');
// 并行执行(快)
const [result1, result2] = await Promise.all([
fetch('/api/data1'),
fetch('/api/data2')
]);
const [data1, data2] = await Promise.all([
result1.json(),
result2.json()
]);
return { data1, data2 };
} catch (error) {
console.error('Error:', error);
}
}
// 错误处理最佳实践
class ApiClient {
constructor(baseURL) {
this.baseURL = baseURL;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const config = {
headers: {
'Content-Type': 'application/json',
...options.headers
},
...options
};
try {
const response = await fetch(url, config);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
} catch (error) {
if (error.name === 'TypeError') {
throw new Error('Network error: Please check your connection');
}
throw error;
}
}
async get(endpoint) {
return this.request(endpoint);
}
async post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
}
// 带重试机制的请求
async requestWithRetry(endpoint, options = {}, maxRetries = 3) {
let lastError;
for (let i = 0; i <= maxRetries; i++) {
try {
return await this.request(endpoint, options);
} catch (error) {
lastError = error;
if (i < maxRetries) {
const delay = Math.pow(2, i) * 1000; // 指数退避
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError;
}
}
// 使用示例
const api = new ApiClient('https://api.example.com');
async function fetchUserData(userId) {
try {
const user = await api.get(`/users/${userId}`);
const posts = await api.get(`/users/${userId}/posts`);
return { user, posts };
} catch (error) {
console.error('Failed to fetch user data:', error.message);
return null;
}
}
ES6+新特性详解
解构赋值和扩展运算符
// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// 默认值
const [a = 10, b = 20] = [1];
console.log(a, b); // 1, 20
// 交换变量
let x = 1, y = 2;
[x, y] = [y, x];
console.log(x, y); // 2, 1
// 对象解构
const person = { name: 'Alice', age: 30, city: 'New York' };
const { name, age, ...others } = person;
console.log(name, age); // 'Alice', 30
console.log(others); // { city: 'New York' }
// 重命名和默认值
const { name: personName, age: personAge, country = 'USA' } = person;
console.log(personName, personAge, country); // 'Alice', 30, 'USA'
// 嵌套解构
const user = {
id: 1,
profile: {
name: 'Bob',
contact: {
email: 'bob@example.com'
}
}
};
const { profile: { name: userName, contact: { email } } } = user;
console.log(userName, email); // 'Bob', 'bob@example.com'
// 函数参数解构
function greet({ name, age = 18 }) {
return `Hello ${name}, you are ${age} years old`;
}
console.log(greet({ name: 'Charlie' })); // "Hello Charlie, you are 18 years old"
// 扩展运算符
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
// 函数参数
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
模板字符串和标签模板
// 基础模板字符串
const name = 'World';
const greeting = `Hello, ${name}!`;
console.log(greeting); // "Hello, World!"
// 多行字符串
const multiline = `
This is a
multiline
string
`;
// 表达式计算
const a = 5, b = 10;
console.log(`The sum is ${a + b}`); // "The sum is 15"
// 标签模板
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`Learn ${searchTerm} programming`;
console.log(text); // "Learn <mark>JavaScript</mark> programming"
// 实用的标签模板函数
function sql(strings, ...values) {
// 简单的SQL注入防护
const escapedValues = values.map(value => {
if (typeof value === 'string') {
return `'${value.replace(/'/g, "''")}'`;
}
return value;
});
return strings.reduce((query, string, i) => {
const value = escapedValues[i] || '';
return query + string + value;
}, '');
}
const userId = 123;
const userName = "O'Connor";
const query = sql`SELECT * FROM users WHERE id = ${userId} AND name = ${userName}`;
console.log(query); // "SELECT * FROM users WHERE id = 123 AND name = 'O''Connor'"
模块化开发
模块化是现代JavaScript 开发的核心概念,它让代码更加组织化、可维护和可重用。
ES Modules (ESM)
// math.js - 导出模块
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// 默认导出
export default function subtract(a, b) {
return a - b;
}
// 也可以这样导出
const divide = (a, b) => a / b;
export { divide };
// main.js - 导入模块
import subtract, { PI, add, multiply, divide } from './math.js';
// 使用导入的功能
console.log(PI); // 3.14159
console.log(add(5, 3)); // 8
console.log(multiply(4, 2)); // 8
console.log(subtract(10, 3)); // 7
console.log(divide(15, 3)); // 5
// 重命名导入
import { add as sum, multiply as product } from './math.js';
console.log(sum(2, 3)); // 5
// 导入所有
import * as MathUtils from './math.js';
console.log(MathUtils.add(1, 2)); // 3
console.log(MathUtils.default(5, 2)); // 3 (默认导出)
CommonJS (Node.js)
// math.js - CommonJS导出
const PI = 3.14159;
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
// 导出方式1
module.exports = {
PI,
add,
multiply
};
// 导出方式2
exports.PI = PI;
exports.add = add;
exports.multiply = multiply;
// 默认导出
module.exports = function subtract(a, b) {
return a - b;
};
// main.js - CommonJS导入
const { PI, add, multiply } = require('./math.js');
const subtract = require('./math.js');
// 或者
const MathUtils = require('./math.js');
console.log(MathUtils.add(1, 2));
动态导入
// 动态导入ES模块
async function loadMathModule() {
try {
const mathModule = await import('./math.js');
console.log(mathModule.add(5, 3)); // 8
// 使用默认导出
console.log(mathModule.default(10, 3)); // 7
} catch (error) {
console.error('模块加载失败:', error);
}
}
// 条件加载
if (someCondition) {
import('./heavy-module.js')
.then(module => {
module.doSomething();
})
.catch(error => {
console.error('模块加载失败:', error);
});
}
// 在函数中动态导入
function processData(data) {
if (data.needsSpecialProcessing) {
return import('./special-processor.js')
.then(processor => processor.process(data));
}
return Promise.resolve(data);
}
模块打包和构建
// webpack.config.js - Webpack配置示例
const path = require('path');
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',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'utils': path.resolve(__dirname, 'src/utils')
}
}
};
// 使用别名导入
import { formatDate } from '@/utils/date.js';
import { apiClient } from 'utils/api.js';
模块设计模式
// 单例模式模块
// config.js
class Config {
constructor() {
if (Config.instance) {
return Config.instance;
}
this.settings = {
apiUrl: 'https://api.example.com',
timeout: 5000
};
Config.instance = this;
}
get(key) {
return this.settings[key];
}
set(key, value) {
this.settings[key] = value;
}
}
export default new Config();
// 工厂模式模块
// logger.js
class Logger {
constructor(level) {
this.level = level;
}
log(message) {
if (this.level >= 1) {
console.log(`[LOG] ${message}`);
}
}
warn(message) {
if (this.level >= 2) {
console.warn(`[WARN] ${message}`);
}
}
error(message) {
if (this.level >= 3) {
console.error(`[ERROR] ${message}`);
}
}
}
export function createLogger(level = 1) {
return new Logger(level);
}
export const defaultLogger = createLogger(2);
JavaScript的核心原理和ES6+特性为现代Web开发提供了强大的基础。掌握这些概念能让你写出更优雅、更高效的代码。
📚 参考学习资料
📖 官方文档
- MDN JavaScript 指南 - 最权威的JavaScript学习资源
- ECMAScript 规范 - JavaScript语言规范
- V8 开发者文档 - V8引擎官方文档
🎓 优质教程
- JavaScript.info - 现代JavaScript教程
- You Don’t Know JS - 深入理解JavaScript系列
- JavaScript 30 - 30天JavaScript挑战
🛠️ 实践项目
- JavaScript 算法与数据结构 - 算法实现
- 33 JS Concepts - 核心概念实践
- Clean Code JavaScript - 代码质量实践
🔧 开发工具
- Chrome DevTools - 浏览器调试工具
- Node.js REPL - JavaScript运行环境
- CodePen - 在线代码编辑器
📝 深入阅读
- JavaScript 引擎基础 - 引擎优化原理
- Event Loop 详解 - 事件循环机制
- 内存管理深入 - 垃圾回收机制
💡 学习建议:建议先通过MDN和JavaScript.info掌握基础概念,然后通过实践项目加深理解,最后阅读深度文章了解底层原理。
Last updated on