JavaScript 核心特性综合实战 —— 从函数到对象的深度应用

JavaScript 核心特性综合实战 —— 从函数到对象的深度应用
(2026年视角 · 中高级进阶 · 强烈建议全部手敲)

下面这套综合实战题目把 JavaScript 最核心、最常被考察的几个特性(函数、闭包、this、原型、对象操作)全部串起来,难度从易到难,适合用来:

  • 查漏补缺
  • 面试前一周冲刺
  • 真正搞懂“函数即对象”这句话的深层含义

实战题目清单(建议按顺序完成)

Level 1:基础函数与闭包暖身(必做)

// 1. 实现一个只能调用一次的函数(once)
function once(fn) {
  // 你的实现
}

const log = once(() => console.log("我只会被打印一次"));
log(); // 打印
log(); // 无输出
log(); // 无输出

// 2. 实现一个累加器(使用闭包)
function createCounter() {
  // 返回的对象包含三个方法:increment, decrement, value
}

const counter = createCounter();
console.log(counter.value());    // 0
counter.increment();
counter.increment();
console.log(counter.value());    // 2
counter.decrement();
console.log(counter.value());    // 1

Level 2:this 指向地狱 + call/apply/bind 大乱斗

// 3. 下面这段代码输出是什么?如何修改让它正确输出 10, 20, 30?
const obj = {
  value: 10,
  getValue: function() {
    return this.value;
  }
};

const fn1 = obj.getValue;
console.log(fn1());           // ?

const fn2 = obj.getValue.bind(obj);
console.log(fn2());           // ?

const fn3 = obj.getValue.call({ value: 30 });
console.log(fn3());           // ?

// 4. 实现一个简易的 bind 方法(不要使用原生的 bind)
Function.prototype.myBind = function(context, ...args) {
  // 你的实现
};

function sayHello(greeting, punctuation) {
  console.log(`${greeting}, 我是 ${this.name}${punctuation}`);
}

const person = { name: "小明" };
const boundSay = sayHello.myBind(person, "你好");
boundSay("!");  // 你好, 我是 小明!

Level 3:原型链 + 对象操作深度融合

// 5. 实现一个深拷贝(处理循环引用 + 常见特殊类型)
function deepClone(obj, visited = new WeakMap()) {
  // 你的实现(要能处理:对象、数组、Date、RegExp、函数、循环引用)
}

// 测试用例
const original = {
  a: 1,
  b: [2, 3],
  c: new Date(),
  d: /test/gi,
  e: function() { console.log("fn"); },
  f: null,
  g: undefined,
  self: null // 循环引用
};
original.self = original;

const copy = deepClone(original);
console.log(copy === original);           // false
console.log(copy.self === copy);          // true(循环引用正确处理)
console.log(copy.c instanceof Date);      // true

Level 4:终极综合题 —— 实现一个“带记忆的计算属性”对象(Vue computed 简化版)

/**
 * 实现一个 createComputedObj 函数
 * 它接收一个对象,对象的值可以是普通值或函数(计算属性)
 * 返回的对象中,所有计算属性都是惰性求值 + 缓存的
 * 当依赖的普通值变化时,相关计算属性缓存失效
 */

const data = createComputedObj({
  firstName: "张",
  lastName: "三",
  fullName() {
    return this.firstName + this.lastName;
  },
  greeting() {
    return `你好,${this.fullName}!`;
  }
});

console.log(data.fullName);     // "张三"
console.log(data.greeting);     // "你好,张三!"

// 修改依赖
data.firstName = "李";
console.log(data.fullName);     // "李三"(重新计算)
console.log(data.greeting);     // "你好,李三!"(greeting 也重新计算)

// 再次访问,不重新计算
console.log(data.fullName);     // "李三"(直接从缓存取)

参考答案思路提示(建议先自己做完再看)

  1. once → 使用闭包 + 标志位(或 WeakMap 存储函数)
  2. createCounter → 闭包保存 count 私有变量
  3. this 指向 → 普通函数调用 this 丢失,bind/call 显式绑定
  4. myBind → 返回新函数 + 拼接参数 + 处理 new 调用情况
  5. deepClone → 递归 + WeakMap 记录已克隆对象 + 特殊类型单独处理(Date/Date、RegExp、函数可直接返回或深拷贝)
  6. createComputedObj → 使用 Proxy + 依赖收集(最简版可用 Map 记录依赖关系 + 缓存 Map)

推荐完成顺序 & 时间建议(总计 4~8 小时)

1~2题(闭包基础)          30~60分钟
3~4题(this & bind)       60~90分钟
5题(深拷贝)               90~120分钟
6题(终极综合)             120~180分钟(最有价值)

全部做完后,你会对下面这些核心概念有质的飞跃

  • 函数是一等公民 & 函数即对象
  • 闭包的真正用途(私有变量 + 记忆 + 模块化)
  • this 动态绑定本质
  • 原型链与属性查找机制
  • 现代 JS 对象操作(Proxy、WeakMap、Symbol 等)

如果你已经做完某几道题,欢迎贴出你的代码,我帮你 review 优化!
或者直接说“我卡在第X题”,我给你更细致的思路引导~

文章已创建 3806

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部