【ECMAScript 学习笔记】5.关于 Class
Class基本语法
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class
关键字,可以定义类:
// 定义 Point 类
class Point {
// 定义 Ponit 类的构造函数
constructor(x, y) {
this.x = x;
this.y = y;
}
// 定义方法
toString() {
console.log(`x:${this.x}, y:${this.y}`);
}
}
ES6 的类,完全可以看作构造函数的另一种写法:
class Point {
constructor() {
}
};
console.log(typeof Point); // "function"
console.log(Point === Point.prototype.constructor); // true
事实上,类的所有方法都定义在类的 prototype
属性上。在类的实例上调用方法,其实就是调用原型的方法。*
Object.assign
方法可以向类添加多个方法:
Object.assign(Point.prototype,{
toValue() {},
toString() {}
})
ES6 中类的内部所有定义的方法,都是不可枚举的,这一点与 ES5 的行为不一致。
class Point {
constructor(){}
toString(){}
}
console.log(Object.keys(Point.prototype)); // []
若想要获取其内部定义的所有方法,则可通过 Object.getOwnPropertyNames
方法获取
console.log(Object.getOwnPropertyNames(Point.prototype));
可使用表达式定义类的属性名
let methodName = "getArea";
class Square {
constructor(){}
[methodName](){}
}
constructor 方法
constructor
方法是类的默认方法,通过 new
命令生成对象实例。自动调用该方法。一个对象必须有 constructor
方法,如果没有显示定义,一个空的 constructor
方法会被默认添加。
constructor
方法默认返回实例对象(即 this
),完全可以指定返回另一个对象。
class Foo {
constructor() {
return Object.create(null);
}
}
Class 表达式
与函数一样, Class 也可以使用表达式的形式定义。
const MyClass = class Me {
getClassName() {
return Me.name;
}
}
Class 的继承
Class 之间可以通过 extends
关键字实现继承,这比 ES5 通过修改原型链实现继承,要清晰和方便很多:
class ColorPoint extends Point {
constructor(x,y) {
super(x,y); // 用于表示 父类的构造函数,用来新建父类的 this 对象。
}
}
子类必须在 constructor
方法中调用 super
方法,否则新建实例会报错。这是因为子类没有自己的 this
对象,而是继承父类的 this
对象,然后对其进行加工。
ES5 的继承,实质是先创造子类的实例对象 this
,然后再将父类的方法添加到 this
上(Parent.applu(this)
)。ES6 的继承机制完全不同,实质是先创造父类的实例对象 this
(所以必须先调用 super
方法),然后再用子类的构造函数修改 this
类的 prototype 属性和 proto 属性
大多数浏览器的 ES5 实现之中,每一个对象都有 __proto__
属性,指向对应的构造函数的 prototype
属性。
Class 作为构造函数的语法糖,同时有 prototype
和 __proto__
属性,因此同时存在两条继承链:
- 子类的
__proto__
属性,表示构造函数的继承,总是指向父类 - 子类
prototype
属性的__proto__
属性,表示方法的继承,总是指向父类的prototype
属性。
Object.getPrototypeOf
Object.getPrototypeOf
方法可以从子类上获取父类
Object.getPrototypeOf(ColorPoint); // Ponit
super 关键字
- 作为函数调用时,
super
代表父类的构造函数。 - 作为调用时,
super
代表父类,可以直接引用父类实例的属性和方法,也可以引用父类的静态方法。
实例的 proto 属性
子类实例的 __proto__
属性的 __proto__
属性,指向父类实例的 __proto
属性。
Class 的取值函数(getter)和存值函数(setter)
与 ES5 一样,在 Class 内部可以使用 get
和 set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class MyClass {
constructor() {
this.element = '';
}
get prop() {
return this.element;
}
set prop(value) {
this.element = value;
}
}
Class 的静态方法
在方法前加上 static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用。
class MyClass {
constructor() {
this.element = '';
}
static classMethod() {
return false;
}
}
MyClass.classMethod();
new.target 属性
new.target
属性用于确定构造函数是怎么调用的。在构造函数中返回 new
命令作用于的那个对象函数,如果不是通过 new
命令调用的,则返回 undefined
。
上一篇: HashMap为什么这么快? ---深入理解HashMap的散列机制
下一篇: 分类管理与标签管理