ja类主体和方法定义
类主体和方法定义
类的主体是放在大括号中的部分{}
。在这里定义类成员,例如方法或构造函数。
严格模式
类的主体以严格模式执行,即,此处编写的代码将采用更严格的语法以提高性能,否则将抛出一些其他的静默错误,并且某些关键字保留给将来的ECMAScript版本。
建设者
该constructor
方法是用于创建和初始化使用创建的对象的特殊方法class
。在一个类中,只能有一个名为“ constructor”的特殊方法。SyntaxError
如果该类包含一个以上的constructor
方法实例,则将引发A。
构造函数可以使用super
关键字来调用超类的构造函数。
原型方法
另请参见方法定义。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Rectangle { constructor(height, width) { this .height = height; this .width = width; } // Getter get area() { return this .calcArea(); } // Method calcArea() { return this .height * this .width; } } const square = new Rectangle(10, 10); console.log(square.area); // 100 |
静态方法
的static
关键字定义为一类的静态方法。静态方法被称为没有实例化的类并不能通过类实例调用。静态方法通常用于为应用程序创建实用程序功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class Point { constructor(x, y) { this .x = x; this .y = y; } static distance(a, b) { const dx = a.x - b.x; const dy = a.y - b.y; return Math.hypot(dx, dy); } } const p1 = new Point(5, 5); const p2 = new Point(10, 10); p1.distance; //undefined p2.distance; //undefined console.log(Point.distance(p1, p2)); // 7.0710678118654755 |
this
与原型和静态方法绑定
当调用静态或原型方法而没有for的值时 this
,例如通过将变量分配给该方法然后调用它,则该this
值将undefined
在方法内部。即使"use strict"
指令不存在,此行为也将是相同的,因为class
主体的语法边界内的代码始终以严格模式执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Animal { speak() { return this ; } static eat() { return this ; } } let obj = new Animal(); obj.speak(); // the Animal object let speak = obj.speak; speak(); // undefined Animal.eat() // class Animal let eat = Animal.eat; eat(); // undefined |
如果我们在非严格模式下使用传统的基于函数的语法重写以上内容,则this
方法调用将自动绑定到初始this
值,默认情况下,该初始值为全局对象。在严格模式下,将不会发生自动绑定。this
保持不变的价值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function Animal() { } Animal.prototype.speak = function () { return this ; } Animal.eat = function () { return this ; } let obj = new Animal(); let speak = obj.speak; speak(); // global object (in non–strict mode) let eat = Animal.eat; eat(); // global object (in non-strict mode) |
实例属性
实例属性必须在类方法内定义:
1 2 3 4 5 6 | class Rectangle { constructor(height, width) { this .height = height; this .width = width; } } |
静态(类方面)数据属性和原型数据属性必须在ClassBody声明之外定义:
1 2 | Rectangle.staticWidth = 20; Rectangle.prototype.prototypeWidth = 25; |
现场申报
公共和私有字段声明是JavaScript标准委员会TC39提出的实验性功能(第3阶段)。对浏览器的支持是有限的,但是可以通过构建步骤(如Babel)使用该功能。
公共领域声明
使用JavaScript字段声明语法,上面的示例可以写成:
1 2 3 4 5 6 7 8 | class Rectangle { height = 0; width; constructor(height, width) { this .height = height; this .width = width; } } |
通过预先声明字段,类定义变得更加自我记录,并且字段始终存在。
如上所示,可以使用默认值或不使用默认值来声明字段。
有关更多信息,请参见公共类字段。
私人领域声明
使用私有字段,可以按以下方式细化定义。
1 2 3 4 5 6 7 8 | class Rectangle { #height = 0; #width; constructor(height, width) { this . #height = height; this . #width = width; } } |
从类外部引用私有字段是错误的。它们只能在类主体中读取或写入。通过定义在类外部不可见的内容,可以确保类的用户不会依赖于内部,这可能会导致版本之间的差异。
私有字段只能在字段声明中预先声明。
以后无法通过分配普通属性的方式来分配专用字段来创建专用字段。
有关更多信息,请参见私有类字段。
子分类 extends
该extends
关键字用于类声明或类表达式中,以将一个类创建为另一个类的子级。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Animal { constructor(name) { this .name = name; } speak() { console.log(`${ this .name} makes a noise.`); } } class Dog extends Animal { constructor(name) { super (name); // call the super class constructor and pass in the name parameter } speak() { console.log(`${ this .name} barks.`); } } let d = new Dog( 'Mitzie' ); d.speak(); // Mitzie barks. |
如果子类中存在构造函数,则需要先调用super(),然后再使用“ this”。
也可以扩展传统的基于功能的“类”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function Animal (name) { this .name = name; } Animal.prototype.speak = function () { console.log(`${ this .name} makes a noise.`); } class Dog extends Animal { speak() { console.log(`${ this .name} barks.`); } } let d = new Dog( 'Mitzie' ); d.speak(); // Mitzie barks. // For similar methods, the child's method takes precedence over parent's method |
请注意,类不能扩展常规(不可构造)对象。如果要从常规对象继承,则可以使用Object.setPrototypeOf()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | const Animal = { speak() { console.log(`${ this .name} makes a noise.`); } }; class Dog { constructor(name) { this .name = name; } } // If you do not do this you will get a TypeError when you invoke speak Object.setPrototypeOf(Dog.prototype, Animal); let d = new Dog( 'Mitzie' ); d.speak(); // Mitzie makes a noise. |
种类
您可能要返回Array
派生数组类中的对象MyArray
。种类模式可让您覆盖默认构造函数。
例如,当使用诸如这样的方法map()
返回默认构造函数时,您希望这些方法返回父Array
对象而不是MyArray
对象。该Symbol.species
符号使您可以执行此操作:
1 2 3 4 5 6 7 8 9 10 | class MyArray extends Array { // Overwrite species to the parent Array constructor static get [Symbol.species]() { return Array; } } let a = new MyArray(1,2,3); let mapped = a.map(x => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true |
超级班级通话 super
该super
关键字用来调用父类的相应方法。与基于原型的继承相比,这是一个优势。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Cat { constructor(name) { this .name = name; } speak() { console.log(`${ this .name} makes a noise.`); } } class Lion extends Cat { speak() { super .speak(); console.log(`${ this .name} roars.`); } } let l = new Lion( 'Fuzzy' ); l.speak(); // Fuzzy makes a noise. // Fuzzy roars. |
混入
抽象子类或混入是类的模板。ECMAScript类只能有一个超类,因此,例如,无法从工具类进行多重继承。该功能必须由超类提供。
具有超类作为输入和扩展该超类作为输出的子类的函数可用于在ECMAScript中实现混入:
1 2 3 4 5 6 7 | let calculatorMixin = Base => class extends Base { calc() { } }; let randomizerMixin = Base => class extends Base { randomize() { } }; |
然后,可以使用以下方式编写使用这些混入的类:
1 2 | class Foo { } class Bar extends calculatorMixin(randomizerMixin(Foo)) { } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!