实现 console.log 代理方法

定义 log 方法代理 console.log,支持参数透传

问题

定义一个 log 方法,让它可以代理 console.log 的方法。

解答

基础实现

// 方式一:使用 rest 参数 + spread 语法
function log(...args) {
  console.log(...args);
}

// 方式二:使用 apply 转发参数
function log() {
  console.log.apply(console, arguments);
}

// 方式三:直接绑定
const log = console.log.bind(console);

// 测试
log('hello');           // hello
log('a', 'b', 'c');     // a b c
log({ name: 'test' });  // { name: 'test' }

增强版:添加前缀和时间戳

function createLogger(prefix = '') {
  return function(...args) {
    const time = new Date().toLocaleTimeString();
    // 在原有参数前添加时间和前缀
    console.log(`[${time}]${prefix}`, ...args);
  };
}

const log = createLogger('[App]');

log('启动成功');        // [10:30:45][App] 启动成功
log('用户数:', 100);    // [10:30:45][App] 用户数: 100

完整代理:支持所有 console 方法

const logger = {};

// 代理 console 的所有方法
['log', 'warn', 'error', 'info', 'debug'].forEach(method => {
  logger[method] = function(...args) {
    const time = new Date().toLocaleTimeString();
    console[method](`[${time}]`, ...args);
  };
});

// 测试
logger.log('普通日志');    // [10:30:45] 普通日志
logger.warn('警告信息');   // [10:30:45] 警告信息
logger.error('错误信息');  // [10:30:45] 错误信息

使用 Proxy 实现

const logger = new Proxy(console, {
  get(target, prop) {
    if (typeof target[prop] === 'function') {
      return function(...args) {
        const time = new Date().toLocaleTimeString();
        // 调用原始方法,添加时间前缀
        target[prop].call(target, `[${time}]`, ...args);
      };
    }
    return target[prop];
  }
});

logger.log('test');   // [10:30:45] test
logger.warn('warn');  // [10:30:45] warn

关键点

  • 使用 ...args rest 参数收集所有参数,再用 spread 展开传递
  • apply 可以将类数组 arguments 作为参数列表传递
  • bind 返回绑定了 this 的新函数,最简洁
  • 代理模式可以在不修改原方法的情况下增加功能(如日志时间、前缀)
  • Proxy 可以拦截对象的所有属性访问,实现更灵活的代理