Skip to content

JavaScript 进阶概念

更新: 8/6/2025 字数: 0 字 时长: 0 分钟

闭包

闭包是指一个函数可以访问其词法作用域外的变量。

js
function createCounter() {
  let count = 0;
  
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

在上面的例子中,内部函数可以访问外部函数的 count 变量,即使外部函数已经执行完毕。

原型和原型链

JavaScript 中的每个对象都有一个原型(prototype),对象可以从原型继承属性和方法。

js
function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  return `Hello, my name is ${this.name}`;
};

const person = new Person('Jensen');
console.log(person.greet()); // "Hello, my name is Jensen"

原型链是 JavaScript 实现继承的机制:

js
function Employee(name, title) {
  Person.call(this, name);
  this.title = title;
}

// 设置原型链
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;

// 添加或覆盖方法
Employee.prototype.greet = function() {
  return `Hello, I'm ${this.name}, the ${this.title}`;
};

const employee = new Employee('Jensen', 'Developer');
console.log(employee.greet()); // "Hello, I'm Jensen, the Developer"

this 关键字

this 关键字的值取决于函数的调用方式:

js
// 全局上下文
console.log(this); // 在浏览器中是 window,在 Node.js 中是 global

// 对象方法中
const obj = {
  name: 'Jensen',
  greet() {
    console.log(this.name); // 'Jensen'
  }
};
obj.greet();

// 构造函数中
function Person(name) {
  this.name = name;
  console.log(this); // Person 实例
}
const person = new Person('Jensen');

// 显式绑定
function greet() {
  console.log(`Hello, ${this.name}`);
}
greet.call({ name: 'Jensen' }); // "Hello, Jensen"
greet.apply({ name: 'Jensen' }); // "Hello, Jensen"
const boundGreet = greet.bind({ name: 'Jensen' });
boundGreet(); // "Hello, Jensen"

// 箭头函数
const obj2 = {
  name: 'Jensen',
  greet: function() {
    const arrowFunc = () => {
      console.log(this.name); // 'Jensen'
    };
    arrowFunc();
  }
};
obj2.greet();

事件循环和异步编程

JavaScript 是单线程的,但通过事件循环机制实现异步编程。

js
console.log('Start');

setTimeout(() => {
  console.log('Timeout');
}, 0);

Promise.resolve().then(() => {
  console.log('Promise');
});

console.log('End');

// 输出顺序:
// Start
// End
// Promise
// Timeout

Promise

Promise 是处理异步操作的对象,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。

js
const fetchData = () => {
  return new Promise((resolve, reject) => {
    // 模拟异步操作
    setTimeout(() => {
      const data = { id: 1, name: 'Jensen' };
      // 成功时
      resolve(data);
      // 失败时
      // reject(new Error('Failed to fetch data'));
    }, 1000);
  });
};

fetchData()
  .then(data => {
    console.log('Data:', data);
    return data.id;
  })
  .then(id => {
    console.log('ID:', id);
  })
  .catch(error => {
    console.error('Error:', error.message);
  })
  .finally(() => {
    console.log('Operation completed');
  });

异步/等待

async/await 是基于 Promise 的语法糖,使异步代码更易读。

js
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ id: 1, name: 'Jensen' });
    }, 1000);
  });
};

const fetchUserData = async () => {
  try {
    console.log('Fetching data...');
    const data = await fetchData();
    console.log('Data:', data);
    return data;
  } catch (error) {
    console.error('Error:', error.message);
  } finally {
    console.log('Operation completed');
  }
};

fetchUserData().then(data => {
  console.log('Processed data:', data);
});

模块化

ES6 引入了原生模块系统:

js
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

const multiply = (a, b) => a * b;
export default multiply;

// main.js
import multiply, { add, subtract } from './math.js';

console.log(add(5, 3));       // 8
console.log(subtract(5, 3));   // 2
console.log(multiply(5, 3));   // 15

设计模式

单例模式

js
const Singleton = (function() {
  let instance;
  
  function createInstance() {
    return { data: 'Singleton instance' };
  }
  
  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true

工厂模式

js
function createUser(type) {
  if (type === 'admin') {
    return {
      name: 'Admin',
      permissions: ['read', 'write', 'delete']
    };
  } else if (type === 'user') {
    return {
      name: 'User',
      permissions: ['read']
    };
  }
}

const admin = createUser('admin');
const user = createUser('user');

观察者模式

js
class EventEmitter {
  constructor() {
    this.events = {};
  }
  
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(listener);
  }
  
  emit(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach(listener => listener(...args));
    }
  }
  
  off(event, listener) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(l => l !== listener);
    }
  }
}

const emitter = new EventEmitter();

function onUserCreated(user) {
  console.log('User created:', user);
}

emitter.on('userCreated', onUserCreated);
emitter.emit('userCreated', { name: 'Jensen' });

函数式编程

js
// 纯函数
const add = (a, b) => a + b;

// 高阶函数
const twice = (fn) => (a, b) => fn(fn(a, b), fn(a, b));
const addTwice = twice(add);
console.log(addTwice(1, 2)); // add(add(1, 2), add(1, 2)) = add(3, 3) = 6

// 柯里化
const curry = (fn) => {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      };
    }
  };
};

const sum = (a, b, c) => a + b + c;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
console.log(curriedSum(1, 2)(3)); // 6
console.log(curriedSum(1)(2, 3)); // 6

// 组合
const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x);
const double = x => x * 2;
const increment = x => x + 1;
const doubleAndIncrement = compose(increment, double);
console.log(doubleAndIncrement(3)); // double(3) = 6, increment(6) = 7