类
类觉不爱【大误】
系列文章
这是JavaScript
系列文章:
知识点
类
什么是类?
JavaScript中的类是语法糖,一种基于原型的继承的语法糖。
类有什么作用?
类是面向对象编程的必备条件。
怎么使用类?
使用
new
来使用一个之前已经声明好的类。
类里面的方法体不需要添加逗号或者分号隔离
声明
class(类声明)
-
基础语法
// extends是继承的语法,书写后 `子类 extends 父类` class name [extends] { // class body }
-
构造函数可选
-
类声明不可以提升
与函数声明不同的是类声明不能提升,所以类声明必须先定义,而函数声明可以先使用再定义。 -
示例一
class Human { constructor(name, weight, height) { this.name = name; this.weight = weight; this.height = height; this.bmi = weight / height / height; } } console.log('bmi: ' + new Human('匿旅', 71, 1.72).bmi); // expected output: bmi: 23.99945916711736
-
示例二
class Human { constructor(weight, height) { this.name = '人类'; this.weight = weight; this.height = height; this.bmi = weight / height / height; } } class Programmer extends Human { constructor(weight, height) { super(weight, height); this.name = '程序员'; } } let iter = new Programmer(71, 1.72); console.log('name: ' + iter.name); // name: 程序员 console.log('bmi: ' + iter.bmi); // bmi: 23.99945916711736
-
注意
- 不要重复声明一个类会报错
class Human { } class Human { }
- 类表达式定义一个类后再声明一个类同样会报错
ORlet Human = class { } class Human { }
class Human { } let Human = class { }
- 报错图示
- 不要重复声明一个类会报错
类表达式
- 基础语法
/** * className 写的话只能在后面的类体内访问到,不写的话就是一个匿名 * exteds 继承父类 * 这个类可以理解为名字为 MyClass */ const MyClass = class [className] [extends] { // class body };
- 示例一:使用类表达式
let World = class { constructor() { } bar () { return 'Hello World!'; } } let instance = new World(); instance.bar(); // "Hello World!"
- 示例二:命名类表达式
NamedWorld
是不对外的,可以理解为一个私有类名,在外部无法访问,对外访问只能通过World
或者new World()
使用let World = class NamedWorld { constructor() { } whoIsThere() { return NamedWorld.name; } } let asia = new World(); asia.whoIsThere(); NamedWorld.name; // 会报错 World.name;
class(类声明) 和 类表达式 区别
- 类声明必须有类名,类表达式可以没有类名。
构造方法
-
constructor
创建 和 初始化class
创建对象的特殊方法,类似JAVA、C#的构造函数,只不过javascript需要借助关键字constructor
.
一个类中只能有 一个 构造方法constructor
JavaScript内的构造方法是可选的,可以不写构造函数,这样JavaScript会声明一个默认的构造函数。 -
基础语法
constructor([arguments]) { ... }
-
默认构造函数
- 基类构造函数
consturctor() { }
- 派生类构造函数
constructor(...args) { super(...args); }
- 基类构造函数
-
示例一
- 问题:如何调用
get
和set
函数?- get
直接使用实例对象.属性
let p = new Parent(); console.log(p.age);
- set
直接赋值实例对象.属性 = xxx
let p = new Parent(); p.age = 23;
- get
class Polygon { // ..and an (optional) custom class constructor. If one is // not supplied, a default constructor is used instead: // constructor() { } constructor(height, width) { this.name = 'Polygon'; this.height = height; this.width = width; } } class Square extends Polygon { constructor(length) { // 在这里, 它调用了父类的构造函数, 并将 length 提供给 Polygon 的"width"和"height" super(length, length); // 注意: 在派生类中, 必须先调用 super() 才能使用 "this"。 // 忽略这个,将会导致一个引用错误。 this.name = '正方形'; } get area () { return this.height * this.width; } set area(value) { // 注意:不能使用 this.area = value 为area赋值 // 否则会导致循环call setter方法导致爆栈 this._area = value; } }
- 问题:如何调用
-
示例二
polygon
prototypeSquare 类的原型被改变,但是在正在创建一个新的正方形实例时,仍然调用前一个基类 Polygon 的构造函数。
class Polygon { constructor() { this.name = 'Polygon'; } } class Square extends Polygon { constructor() { super(); } } class Rectangle { } Object.setPrototypeOf(Square.prototype, Rectangle.prototype); console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); // false console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); // true let newInstance = new Square(); console.log(newInstance.name); // Polygon
super
-
简介
- super关键字 至多出现 一次
- 必须在使用
this
关键字之前使用 - super关键字 也可以用来调用父对象上的函数。
-
基础语法
// 调用 父对象/父类 构造函数 super([ arguments ]); // 调用 父对象/父类 上的方法 super.functionOfParent([ arguments ]);
-
调用父类上的静态方法
class Human { constructor() { } static ping() { return 'ping'; } } class Computer extends Human { constructor() { } static pingpong() { return super.ping() + ' pong'; } } Computer.pingpong(); // "ping pong"
-
不能使用
delete
删除父类的属性class Base { constructor() { } foo() { } } class Derived extends Base { constructor() { } delete () { delete super.foo; } } new Derived().delete();
extends
-
简介
类声明 和 类表达式 都可以使用 extends ,用来创建一个子类继承另一个类-
还有一段我开始不太懂得话:
- 继承的.prototype必须是一个Object 或者 null。
let Parent = 8; // Number/Boolean/String class Child extends Parent {} // 这里会报错
- 继承的.prototype必须是一个Object 或者 null。
-
-
示例一
继承内置的Date
对象class MyDate extends Date { constructor() { super(); } getFormattedDate() { let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; return this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear(); } }
-
示例二
class nullExtends extends null { constructor() { } } Object.getPrototypeOf(nullExtends); Object.getPrototypeOf(nullExtends.prototype); new nullExtends();
static
-
简介
- static 关键字声明静态方法
- 不能在类的实例上调用静态方法
- 只能使用类本身调用静态方法
-
基础语法
static methodName() { ... }
-
示例一:同一个类中调用其他静态方法
class StaticMethods { static outputLog() { return 'output log'; } static debug() { return this.outputLog() + ' debug'; } } // 使用 StaticMethods.outputLog(); // "output log" StaticMethods.debug(); // "output log debug"
-
示例二:在构造函数或者其他方法内调用静态方法
class Parent { constructor() { console.log(Parent.staticMethod()); console.log(this.constructor.staticMethod()); } static staticMethod() { return 'static'; } } new Parent(); // 调用
-
示例三:子类静态方法调用父类静态方法
class Parent { static staticMethod() { return 'parent static'; } } class Child { static staticMethod1() { return super.staticMethod + ' child static'; } } console.log(Parent.staticMethod()); console.log(Child.staticMethod1());
鸣谢
我们之所以看得远,是因为我们站在了巨人的肩膀上。参考列表: