第一部分:基础入门(5 题)

题 1

创建 Book 类,构造器接收 nameprice;实例方法 info() 输出:书名:xxx,价格:xxx元,实例化一本书并调用方法。

js

运行

// 你的代码

// 答案
class Book {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
  info() {
    console.log(`书名:${this.name},价格:${this.price}元`);
  }
}
const b = new Book("JS高级程序设计", 99);
b.info();

题 2

给类添加实例字段:统一默认分类 tech,不用写在 constructor 里。

js

运行

// 答案
class Book {
  type = "tech";
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
}
const b = new Book("Three.js入门", 79);
console.log(b.type); // tech

题 3 static 静态

创建工具类 Calc,静态属性 PI = 3.14;静态方法 circleArea(r) 计算圆面积 PI*r*r,直接类名调用。

js

运行

// 答案
class Calc {
  static PI = 3.14;
  static circleArea(r) {
    return Calc.PI * r * r;
  }
}
console.log(Calc.circleArea(2));

题 4 getter/setter

学生类,内部私有变量 #score;使用 get score 获取分数,set score 限制分数 0~100,超出抛出错误。

js

运行

// 答案
class Student {
  #score;
  constructor(s) {
    this.#score = s;
  }
  get score() {
    return this.#score;
  }
  set score(val) {
    if (val < 0 || val > 100) throw new Error("分数范围0-100");
    this.#score = val;
  }
}
const s = new Student(80);
console.log(s.score);
s.score = 95;
// s.score = 101 // 报错

题 5 私有方法

类内私有方法 #encrypt,接收字符串简单加密(拼接_secret),外部无法调用,只能内部公开方法调用。

js

运行

// 答案
class User {
  #encrypt(str) {
    return str + "_secret";
  }
  getPwd(pwd) {
    return this.#encrypt(pwd);
  }
}
const u = new User();
console.log(u.getPwd("123456"));
// u.#encrypt("123") 语法报错

第二部分:继承 extends + super(4 题)

题 6 基础继承

父类 Animal:构造器 name,方法 speak 输出动物叫声; 子类 Cat 继承 Animal,构造传 name + color,重写 speak,内部用 super 调用父类方法。

js

运行

// 答案
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name}发出声音`);
  }
}

class Cat extends Animal {
  constructor(name, color) {
    super(name);
    this.color = color;
  }
  speak() {
    super.speak();
    console.log(`${this.color}小猫喵喵叫`);
  }
}
const cat = new Cat("橘猫", "橘色");
cat.speak();

题 7 子类无 constructor

子类不写构造函数,测试能否直接传参实例化,说明原理。

js

运行

class Animal {
  constructor(name) {
    this.name = name;
  }
}
class Dog extends Animal {}
const dog = new Dog("柴犬");
console.log(dog.name); // 柴犬
// 原理:子类无constructor会自动补全 constructor(...args){super(...args)}

题 8 静态方法继承

父类静态方法 logName,子类调用 super.logName()

js

运行

// 答案
class Parent {
  static logName() {
    return "父类静态方法";
  }
}
class Child extends Parent {
  static run() {
    return super.logName();
  }
}
console.log(Child.run());

题 9 继承私有字段测试

父类 #id 私有属性,子类能否直接 this.#id 访问?

js

运行

// 答案:不能,私有字段#仅本类内部可见,子类无法访问
class Parent {
  #id = 1001;
}
class Child extends Parent {
  test() {
    console.log(this.#id); // 语法报错
  }
}

第三部分 this 指向陷阱(3 题,面试高频)

题 10 提取方法后 this 丢失

js

运行

class Demo {
  name = "测试";
  fn() {
    console.log(this.name);
  }
}
const d = new Demo();
const fn = d.fn;
fn(); // 输出?为什么?

答案:undefined 原因:class 内部默认严格模式,单独调用普通函数 this 不指向实例,为 undefined。

题 11 箭头实例字段修复 this

改造上面代码,提取调用不丢失 this。

js

运行

// 答案
class Demo {
  name = "测试";
  fn = () => {
    console.log(this.name);
  }
}
const d = new Demo();
const fn = d.fn;
fn(); // 测试

题 12 bind 绑定修复 this

另一种修复方案:constructor 中 bind 绑定 this

js

运行

// 答案
class Demo {
  constructor() {
    this.name = "测试";
    this.fn = this.fn.bind(this);
  }
  fn() {
    console.log(this.name);
  }
}
const d = new Demo();
const fn = d.fn;
fn();

第四部分:综合大题(2 道,模拟业务)

综合题 1 用户权限管理类

需求:

  1. User 类,私有 #password,公开 username;
  2. get password 只能返回掩码 ******,set password 长度必须≥6;
  3. 静态方法 createAdmin() 返回管理员实例,用户名固定 admin;
  4. 子类 Admin 继承 User,新增私有 #level = 99,方法 getLevel 返回等级。

js

运行

// 参考答案
class User {
  #password;
  constructor(username, pwd) {
    this.username = username;
    this.password = pwd;
  }
  get password() {
    return "******";
  }
  set password(val) {
    if (val.length < 6) throw new Error("密码至少6位");
    this.#password = val;
  }
  static createAdmin() {
    return new User("admin", "admin123");
  }
}

class Admin extends User {
  #level = 99;
  getLevel() {
    return this.#level;
  }
}
const admin = new Admin("root", "1234567");
console.log(admin.password);
console.log(admin.getLevel());

综合题 2 Three.js 简易物体类(前端 3D 方向)

需求:

  1. 基础 MeshBase 类:构造接收 x,y,z 坐标;方法 move (x,y,z) 修改坐标;
  2. 静态工具方法 createCube() 快速返回实例;
  3. 子类 SphereMesh 继承 MeshBase,新增半径 radius,重写 move 打印球体移动日志。

js

运行

// 参考答案
class MeshBase {
  constructor(x = 0, y = 0, z = 0) {
    this.x = x;
    this.y = y;
    this.z = z;
  }
  move(x, y, z) {
    this.x += x;
    this.y += y;
    this.z += z;
  }
  static createCube() {
    return new MeshBase();
  }
}

class SphereMesh extends MeshBase {
  constructor(radius, x, y, z) {
    super(x, y, z);
    this.radius = radius;
  }
  move(x, y, z) {
    super.move(x, y, z);
    console.log(`球体移动,新坐标:${this.x},${this.y},${this.z}`);
  }
}
const sphere = new SphereMesh(2, 1, 1, 1);
sphere.move(2, 0, 0);

附加面试问答题(口头自测)

  1. class 和 ES5 构造函数有什么区别?
  2. static 方法里的 this 指向谁?实例方法 this 指向谁?
  3. #私有属性和下划线_模拟私有有什么本质区别?
  4. super () 和 super.xxx () 分别用在什么场景?
  5. 类方法单独取出调用为什么 this 失效,三种解决方案是什么?

更多推荐