1.类声明
类是一种“特殊的函数”,就像函数声明定义方式和函数表达式定义方式一样,定义类的方式也有两种:类声明定义方式和类表达式定义方式。
//类声明定义方式
class Rectangle {
//类体
}
//类表达式定义方式
//命名类
let Rectangle = class Rectangle2 {
//类体
};
console.log(Rectangle.name);
//输出类名称: "Rectangle2"
//未命名/匿名类
let Rectangle = class {
//类体
};
console.log(Rectangle.name);
//输出类名称: "Rectangle"
2.继承
一个类只能继承自一个父类,不可以继承自多个父类。
class 子类名 extends 父类名 {
//类体
}
3.抽象(Abstract)类
虽然ECMAScript没有专门支持抽象类的语法,但是我们可以通过new.target
来实现抽象类。通过在实例化时检测new.target
是不是抽象基类,可以阻止对抽象基类的实例化。
class Vehicle {
constructor() {
console.log(new.target);
if (new.target === Vehicle) {
throw new Error('Vehicle cannot be directly instantiated');
}
}
}
//继承
class Bus extends Vehicle {}
//class Bus {}
new Bus();
//Error: Vehicle cannot be directly instantiated
new Vehicle();
4.重写(Override)
可以在抽象父类构造函数中进行检查,可以要求子类必须定义某个方法。
class Vehicle {
constructor() {
if (new.target === Vehicle) {
throw new Error('Vehicle cannot be directly instantiated');
}
if(!this.foo) {
throw new Error('Inheriting class must define foo()');
}
console.log('success!');
}
}
//子类
class Bus extends Vehicle {
foo() {};
}
//子类
class Van extends Vehicle {}
//success
new Bus();
//Error:Inheriting class must define foo()
new Van();
5.构造函数
一个类只能有一个构造函数。
class 类名 {
constructor() {
//构造函数体
}
}
6.静态初始化块(Static Initialization Blocks)
一个类可以有多个静态初始化块。
构造函数是用于实例字段的初始化,而静态初始化块(Static Initialization Blocks)是用于静态字段的初始化。
class 类名 {
static {
//静态初始化块体
}
}
//示例
class ClassWithStaticInitializationBlock {
static staticProperty1 = 'Property 1';
static staticProperty2;
static {
this.staticProperty2 = 'Property 2';
}
}
console.log(ClassWithStaticInitializationBlock.staticProperty1);
//输出
"Property 1"
console.log(ClassWithStaticInitializationBlock.staticProperty2);
//输出
"Property 2"
7.创建对象
//类发明之前的对象创建方式一
//字面量创建方式
let 对象 = {
字段名: 值,
方法名: function() {
//方法体
},
//方法简写
方法名() {
//方法体
}
};
//示例
let person = {
name: "张三",
age: 28,
sayName: function() {
console.log(this.name);
},
//方法简写
sayName() {
console.log(this.name);
}
};
//类发明之前的对象创建方式二
//Object()构造函数创建方式
//Object()可以调用或不调用new,两者一样。
let 对象 = new Object();
对象.字段名 = 值;
对象.方法名 = function() {
//方法体
};
//示例
let person = new Object();
person.name = "张三";
person.age = 28;
person.sayName = function() {
console.log(this.name);
};
//类发明之后的对象创建方式
//类名构造函数创建对象方式
//如果没有参数传递,可省略括号,一般不推荐省略。
let 对象 = new 类名();
let 对象 = new 类名(参数);
对象属性名称可以是字符串、数字、符号。如果对象属性名称不是合法的 Javascript 标识符,它必须用 ""
包裹。
//属性名为car1字符串和数字7
let car = { car1: "Jeep", 7: "Mazda" };
//属性名为不合法的标识符
let unusualPropertyNames = {
"": "An empty string",
"!": "Bang!"
}
8.访问成员
//类定义方式使用.访问
类.静态字段
类.静态方法()
对象.实例字段
对象.实例方法()
//对象字面量方式使用[]访问
//单引号或双引号都可以,没区别
对象['属性名']
对象['方法名']
8.重载(Overload)
JavaScript不支持重载,如果定义了两个同名函数,则后定义的会覆盖先定义的。可以通过检查参数的类型和数量,然后执行不同的逻辑来模拟函数重载。
9.Getter/Setter
Getter/Setter支持静态Getter/Setter和实例Getter/Setter。
Getter/Setter访问控制默认是 public
,另外也支持 private
。
let person = {
firstName: "Bill",
lastName : "Gates",
language : "en",
get lang() {
return this.language;
}
set lang(lang) {
this.language = lang;
}
};
10.可计算属性名
ECMAScript的对象的键往往是确定的,如果想要实现对象的键根据实际情况赋予不同的键的话,那就得用 可计算属性名 这个功能,把需要计算的表达式放在方括号[]
里面。
在ECMA262-5(2009)里面的做法是:
const nameKey = "name";
const ageKey = "age";
const jobKey = "job";
let person = {};
person[nameKey] = 'Matt';
person[ageKey] = 27;
person[jobKey] = 'Software engineer';
console.log(person);
//输出
{ name: 'Matt', age: 27, job: 'Software engineer' }
从ECMA262-6(2015)开始添加了 可计算属性名 这个功能,这里这样做:
const nameKey = "name";
const ageKey = "age";
const jobKey = "job";
let person = {
[nameKey] : 'Matt',
[ageKey] : 27,
[jobKey] : 'Software engineer'
};
console.log(person);
//输出
{ name: 'Matt', age: 27, job: 'Software engineer' }
11.super关键字
使用场景 | 调用方式 |
调用父类的构造函数 | super(参数) ,必须在this 关键字和构造函数返回之前 |
调用父类的属性(支持静态字段、静态方法、实例方法,不支持实例字段) | super.prop 和 super[expr] 两种方式都可以 |
调用父对象字面量的属性(字段、方法) | super.prop 和 super[expr] 两种方式都可以 |
//调用父类的构造函数
class Foo {
constructor(name) {
this.name = name;
}
}
class FooBar extends Foo {
constructor(name, index) {
super(name);
this.index = index;
}
}
//调用父类的属性
class Foo {
static baseStaticField = 90;
static logNbSides() {
return "I have 4 sides";
}
getNameSeparator() {
return '-';
}
}
class FooBar extends Foo {
static extendedStaticField = super.baseStaticField;
static logDescription() {
return super.logNbSides();
}
getFullName() {
return super.getNameSeparator();
}
}
//调用父对象字面量的属性
const obj1 = {
prop: 1,
method1() {
console.log("method 1");
}
};
const obj2 = {
myParent() {
console.log(super.prop);
},
method2() {
super.method1();
}
};
Object.setPrototypeOf(obj2, obj1);
12.this关键字
在非严格模式下,this
的值始终是当前对象的引用。
在严格模式下,this
的值根据其所在的上下文而有所不同:全局、类、函数。
原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/javascript/javascriptlang/4729.html