ES6 class 是语法糖,本质仍是原型链继承,所有继承基于[[Prototype]]链,class声明编译为构造函数并自动设置prototype和constructor,extends通过Object.setPrototypeOf实现继承。
ES6
只是语法糖,底层仍是原型链继承
它没有改变 JavaScript 的继承机制本质——所有继承依然基于
链。所谓“类”,只是把原本用
+
+
手动搭的结构,包装成更接近传统 OOP 语言的写法。
真正执行时,
声明会被编译为构造函数,并自动设置
和
属性;
则会调用
和
。
内部方法默认不可枚举(比手写
更干净)
声明不会被提升(而函数声明会),且必须用
调用,否则报
静态方法和实例方法都通过
或构造函数本身挂载,没新增任何底层机制
如何正确定义
并实现继承?
关键在三步:定义基类、用
继承、子类中必须调用
(哪怕不传参)。
不写
时,子类会自动获得默认构造函数:
必须在访问
之前调用,否则报
静态方法也能被继承:
不会覆盖从
继承来的
,但可通过
显式定义
为什么
和
仍能准确反映真实关系?
因为
没有绕过原型系统,只是让原型链更“规整”。你可以用原生 API 验证它的底层结构:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
指向
(尽管不推荐直接用
)
指向
,这决定了静态属性/方法的继承链
如果你手动修改
(比如赋值为新对象),会断开与
的连接,
就会失效
容易被忽略的细节:私有字段、
和装饰器兼容性
ES6
本身不支持私有成员,直到 ES2022 才加入
语法;而
在
构造器中行为更严格——它能区分是否被
调用,这对编写可继承的工具类很关键。
私有字段
是真正的私有(无法被子类访问),不是命名约定(如
)
在基类构造器中指向实际被
的类(比如
时,
),可用于防止类被直接实例化
目前主流装饰器提案(如
)依赖 Babel 或 TypeScript 转译,原生
不支持运行时装饰,这点常被误认为是“类的限制”
真正复杂的地方在于:你得同时理解语法糖表象和原型链实质。一旦遇到奇怪的
失败、
绑定异常或继承链断裂,问题几乎总出在原型操作被意外覆盖,而不是
本身。
class[[Prototype]]functionprototypeObject.setPrototypeOfclassprototypeconstructorextendsObject.setPrototypeOf(SubClass, SuperClass)Object.setPrototypeOf(SubClass.prototype, SuperClass.prototype)classprototypeclassnewTypeError: Class constructor X cannot be invoked without 'new'prototypeclassextendssuper()class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a sound.`;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // ← 必须!否则报 ReferenceError
this.breed = breed;
}
speak() {
return `${this.name} barks.`;
}
}constructorconstructor(...args) { super(...args); }super()thisReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructorDog.isAnimal = trueAnimalisAnimalstatic get isAnimal() { return true; }instanceofObject.getPrototypeOfclassconst dog = new Dog('Max', 'Golden');
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // trueDog.prototype.__proto__Animal.prototype__proto__Dog.__proto__AnimalDog.prototypeAnimal.prototypeinstanceofnew.targetclass#fieldnew.targetclassnew#name_namenew.targetnewnew Dog()new.target === Dog@boundclassinstanceofthisclass