← 返回目录

11. class 类

class 想成"生产对象的模具":就像做手机的模具,定好了品牌、价格,还规定手机能打电话;用同一个模具能压出无数台华为、小米。constructor 是"开机时自动执行的初始化规则",extends 是"拿旧模具改个新模具",super 是"先请旧模具把它那部分造好",static 是"刻在模具上、不属于任何一台手机"的标识。

11.1 互动演示

点按钮看 class / extends / static 的实际输出。

11.2 知识点讲解

① 基本写法:构造函数 + 原型 → class

以前造对象要写"构造函数"再往 prototype 上挂方法,东一块西一块;class 把数据和方法全收进一个花括号里,像把模具图纸钉在一张纸上。

// 以前:构造函数 + 手动挂原型,散在两处
function Phone(brand, price) {   // 构造函数:造手机时传品牌、价格
  this.brand = brand;            // 每个手机的品牌,存到 this 上
  this.price = price;            // 每个手机的价格,存到 this 上
}
Phone.prototype.makeCall = function () {  // 手动把方法挂到原型上(所有手机共用)
  console.log("可以打电话"); // 方法挂在原型上
};

// 现在:class,数据和方法写在一个块里
class Phone {                   // 一个模具图纸,数据 + 方法钉在一张纸上
  constructor(brand, price) { // 造对象时自动跑一次的初始化
    this.brand = brand;        // 把品牌存进这台手机
    this.price = price;        // 把价格存进这台手机
  }
  makeCall() { // 方法直接写里面,不用再挂 prototype
    console.log("可以打电话"); // 这台手机能打电话
  }
}
let p = new Phone("Huawei", 5999); // new 一下,模具压出一台手机

constructor 是"造对象时自动执行"的初始化函数,名字固定不能改。如果你写了 new Phone 却忘了传 brand/price,造出来的手机品牌就是 undefined。方法不用再挂 prototype,集中在类里一眼看清这模具能干什么。

② 继承:extends + super

有了"普通手机模具",想造"智能手机",不用重新开模,extends 就是"在旧模具上改个新模具",super 是"先让旧模具把它那部分造好"。

// 以前:原型链继承,写起来绕
function Smart(brand) {          // 智能手机构造函数
  Phone.call(this, brand);       // 手动借父类构造(.call 把 this 借过去)
}
Smart.prototype = new Phone();   // 手动把原型链连上父类
Smart.prototype.takePhoto = function () { console.log("拍照"); }; // 手动挂新方法

// 现在:extends + super,两行说清楚
class Smart extends Phone { // 新模具继承旧模具(extends = 在旧模具上改)
  constructor(brand, color) {  // 智能手机自己的初始化
    super(brand);              // ★ 先调用父类构造(必须写在 this 之前)
    this.color = color;        // 新模具再加自己的属性(颜色)
  }
  takePhoto() { // 新模具加的新功能
    console.log("拍照");
  }
}
let s = new Smart("Xiaomi", "黑色"); // 压出一台智能手机

如果你在子类的 constructor 里先写了 this.color = color 再调 super,浏览器会直接报错"必须先调用 super"。因为父类那部分还没初始化,this 这台"手机"都还没造出来,你没法给它贴颜色。

③ 静态成员:属于模具,不属于手机

想象模具上刻着一行"Made in 深圳"——这行字是模具自己的,任何一台出厂手机身上都没有。加 static 的东西就是这种"模具级"成员。

class Phone {
  static factory = "深圳某工厂"; // 静态属性:刻在模具上,不属于任何一台手机
  static upgrade() { // 静态方法:模具自己的功能,不用 new
    console.log("模具升级了");   // 直接调模具本身
  }
}
console.log(Phone.factory); // 深圳某工厂(用模具名访问)
Phone.upgrade(); // 模具升级了(用模具名调用)
// new 出来的手机访问不到 factory —— 那是模具上的字

如果你拿 new Phone 出来的手机去读 .factory,得到的是 undefined。因为 static 只挂在类本身上,不挂在实例上——像 Math.maxDate.now 这种"直接拿工具用、不用 new"的方法,就是静态方法的思路。

11.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:Vue/React 里的组件类、写工具类(如封装一个 Request 类、一个 Store 类)、做"多张同结构卡片"的数据模型(如 User、Order、Goods)、需要继承复用逻辑时(父类公共方法 + 子类个性化)。

② 常见的问题:子类 constructor 里 super 忘写或写在 this 之后直接报错;把 static 成员当实例成员读出来是 undefined;this 方法里传出去当回调后 this 丢失(比如 btn.onclick = obj.say)。

③ 解决思路:报错 "must call super" 就把 super 移到 constructor 第一行;读到 undefined 先确认是不是 static;this 丢了就用箭头函数绑住 this,或在 constructor 里 this.say = this.say.bind(this)

一句话:class = 生产对象的模具constructor 初始化、extends + super 继承、static 属于模具本身。