JavaScript案例0322

发布于:2025-03-25 ⋅ 阅读:(36) ⋅ 点赞:(0)

以下是一些涵盖不同高级JavaScript概念和应用的案例,每个案例都有详细解释:


案例1:实现 Promise/A+ 规范的手写 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(fn => fn());
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onFulfilled, onRejected) {
    const promise2 = new MyPromise((resolve, reject) => {
      const microtask = (fn, value) => {
        queueMicrotask(() => {
          try {
            const x = fn(value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      };

      if (this.state === 'fulfilled') {
        microtask(onFulfilled, this.value);
      } else if (this.state === 'rejected') {
        microtask(onRejected, this.reason);
      } else {
        this.onFulfilledCallbacks.push(() => microtask(onFulfilled, this.value));
        this.onRejectedCallbacks.push(() => microtask(onRejected, this.reason));
      }
    });

    return promise2;
  }
}

// 辅助函数处理不同返回值类型
function resolvePromise(promise2, x, resolve, reject) {
  // ...完整实现需要处理thenable对象和循环引用等情况
}

技术点

  • Promise状态机实现
  • 微任务队列(queueMicrotask)
  • 链式调用和值穿透
  • 递归解析处理

案例2:使用 Proxy 实现自动化表单校验

const validator = {
  set(target, prop, value) {
    const rules = {
      username: val => val.length >= 5 && val.length <= 20,
      password: val => /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(val),
      age: val => Number.isInteger(val) && val >= 18
    };

    if (!rules[prop](value)) {
      throw new Error(`Invalid ${prop} value`);
    }
    target[prop] = value;
    return true;
  }
};

const formData = new Proxy({}, validator);

// 使用示例
try {
  formData.username = 'user123'; // 有效
  formData.password = 'pass1234'; // 无效,触发错误
} catch (e) {
  console.error(e.message);
}

技术点

  • Proxy API 的应用
  • 数据劫持与校验
  • 正则表达式验证
  • 自定义错误处理

案例3:实现前端路由系统(Hash模式)

class HashRouter {
  constructor() {
    this.routes = {};
    window.addEventListener('hashchange', this.load.bind(this));
  }

  addRoute(path, callback) {
    this.routes[path] = callback;
  }

  load() {
    const hash = window.location.hash.slice(1) || '/';
    const [path, queryString] = hash.split('?');
    const query = new URLSearchParams(queryString);

    if (this.routes[path]) {
      this.routes[path](Object.fromEntries(query.entries()));
    } else {
      this.routes['404']?.();
    }
  }

  navigate(path, query = {}) {
    const queryStr = new URLSearchParams(query).toString();
    window.location.hash = `${path}${queryStr ? `?${queryStr}` : ''}`;
  }
}

// 使用示例
const router = new HashRouter();
router.addRoute('/about', (params) => {
  console.log('About page', params);
});
router.navigate('/about', { from: 'home' });

技术点

  • Hash路由原理
  • URLSearchParams API
  • 发布-订阅模式
  • 浏览器历史管理

案例4:Web Worker 多线程图像处理

// 主线程
const worker = new Worker('image-worker.js');
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

canvas.addEventListener('change', async (e) => {
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  
  worker.postMessage({
    pixels: imageData.data.buffer,
    width: canvas.width,
    height: canvas.height,
    filterType: 'grayscale'
  }, [imageData.data.buffer]);

  worker.onmessage = ({ data }) => {
    ctx.putImageData(new ImageData(new Uint8ClampedArray(data), 0, 0);
  };
});

// image-worker.js
self.addEventListener('message', ({ data }) => {
  const pixels = new Uint8ClampedArray(data.pixels);
  
  // 应用滤镜(灰度化)
  for (let i = 0; i < pixels.length; i += 4) {
    const avg = (pixels[i] + pixels[i+1] + pixels[i+2]) / 3;
    pixels[i] = avg; // R
    pixels[i+1] = avg; // G
    pixels[i+2] = avg; // B
  }
  
  self.postMessage(pixels.buffer, [pixels.buffer]);
});

技术点

  • Web Worker 多线程
  • Transferable Objects
  • Canvas 像素操作
  • 图像处理算法

案例5:实现 Observable 响应式编程

class Observable {
  constructor(subscribe) {
    this._subscribe = subscribe;
  }

  subscribe(observer) {
    const subscription = {
      unsubscribed: false,
      unsubscribe() {
        this.unsubscribed = true;
      }
    };
    this._subscribe({
      next: val => {
        if (!subscription.unsubscribed) observer.next(val);
      },
      error: err => observer.error?.(err),
      complete: () => observer.complete?.()
    });
    return subscription;
  }

  pipe(...operators) {
    return operators.reduce((prev, fn) => fn(prev), this);
  }

  static fromEvent(element, eventName) {
    return new Observable(observer => {
      const handler = e => observer.next(e);
      element.addEventListener(eventName, handler);
      return () => element.removeEventListener(eventName, handler);
    });
  }
}

// 使用示例
const click$ = Observable.fromEvent(document, 'click')
  .pipe(
    throttle(1000),
    map(e => ({ x: e.clientX, y: e.clientY }))
  );

click$.subscribe({
  next: pos => console.log('Clicked at:', pos)
});

技术点

  • 观察者模式
  • 函数式编程
  • 操作符链式调用
  • 事件流处理

这些案例覆盖了:

  1. 异步编程核心(Promise)
  2. 元编程(Proxy)
  3. 前端架构(路由)
  4. 性能优化(Web Worker)
  5. 响应式编程(Observable)

每个案例都可以进一步扩展实现更多高级功能。例如在Promise实现中添加async/await支持,在路由系统中添加嵌套路由等。