9.1 ES5中的近类结构
创建一个构造函数,然后定义另一个方法并赋值给构造函数。
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name)
}
var person = new Person('Nichilas');
person.sayName(); // Nichilas
ES6中的类也是借助的这个方法
9.2 类的申明
class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
let person = new PersonClass("Nicholas");
console.log(person instanceof PersonClass); // true
console.log(person instanceof Object); // true
- 类声明不会被提升,这与函数定义不同。存在于暂时性死区内。
- 类的所有方法都是不可枚举的,
- 严格模式
- 类的所有方法内部都没有 [[Construct]] ,因此使用 new 来调用它们会抛出错误。
- 调用类构造器时不使用 new ,会抛出错误。
- 在类的方法内部重写类名,会抛出错误。
9.3 类的表达式
创建单例
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}("Nicholas");
person.sayName();
需计算的成员名
9.3.1 基本的类的声明
let PersonClass = class {
}
9.4 作为一等公民的类
9.4.1 基本的类的表达式的语法
let PersonClass = class {
}
9.4.2 命名类表达式
// 具名表达式
let PersonClass = class PersonClass2 {
};
console.log(typeof PersonClass); // "function"
console.log(typeof PersonClass2); // "undefined"
9.5 访问器属性
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}
9.6 可计算成员名称
let methodName = "sayName";
class PersonClass {
constructor(name) {
this.name = name;
}
[methodName]() {
console.log(this.name);
}
}
let me = new PersonClass("Nicholas");
me.sayName(); // "Nicholas"
9.7 生成器方法
class Collection {
constructor() {
this.items = [];
}
*[Symbol.iterator]() {
yield *this.items.values();
}
}
var collection = new Collection();
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for (let x of collection) {
console.log(x);
}
9.8 静态成员
ES6 的类简化了静态成员的创建,只要在方法与访问器属性的名称前添加正式的 static 标注。
class PersonClass {
// 等价于 PersonType 构造器
constructor(name) {
this.name = name;
}
// 等价于 PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
// 等价于 PersonType.create
static create(name) {
return new PersonClass(name);
}
}
let person = PersonClass.create("Nicholas");
静态成员不能用实例来访问,你始终需要直接用类自身来访问它们。
9.9 继承和派生类
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
class Square extends Rectangle {
constructor(length) {
// 与 Rectangle.call(this, length, length) 相同
super(length, length);
}
}
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
9.9.1 类方法的遮蔽
子类中如果有相同方法会覆盖遮蔽父类的方法
class Square extends Rectangle {
constructor(length) {
// 与 Rectangle.call(this, length, length) 相同
super(length, length);
}
getArea() {
return this.length*this.length
// return super.getArea();
}
}
9.9.2 静态成员继承
静态方法能被继承 继承过来也是静态方法
9.9.3 派生自表达式的类
只要一个表达式能够返回一个具有 [[Construct]] 属性以及原型的函数,就可以对其使用 extends 。
下列表达式类型会导致错误:1. null ;2. 生成器函数(详见第八章)
let SerializableMixin = {
serialize() {
return JSON.stringify(this);
}
};
let AreaMixin = {
getArea() {
return this.length * this.width;
}
};
function mixin(...mixins) {
var base = function() {};
Object.assign(base.prototype, ...mixins);
return base;
}
class Square extends mixin(AreaMixin, SerializableMixin) {
constructor(length) {
super();
this.length = length;
this.width = length;
}
}
var x = new Square(3);
9.9.4 内建对象的继承
ES6中很多内建对象可以被继承 并且保持功能 在ES5中不能保持相同功能。在 ES6 基于类的继承中, this 的值会先被基类( Array )创建,随后才被派生类的构造器( MyArray )所修改。结果是 this 初始就拥有作为基类的内置对象的所有功能,并能正确接收与之关联的所有功能。
class MyArray extends Array {
// 代码块
}
var colors = new MyArray();
colors[0] = "red";
console.log(colors.length); // 1
colors.length = 0;
console.log(colors[0]); // undefined
9.9.5 Symbol.species属性
继承内置对象能任意能返回内置对象实例的方法,在派生类上却会自动返回派生类的实例。因此,若你拥有一个继承了 Array 的派生类 MyArray ,诸如 slice() 之类的方法都会返回 MyArray 的实例。
class MyArray extends Array {
// 空代码块
}
let items = new MyArray(1, 2, 3, 4),
subitems = items.slice(1, 3);
console.log(items instanceof MyArray); // true
console.log(subitems instanceof MyArray); // true
Symbol.species 被用于定义一个能返回函数的静态访问器属性。每当类实例的方法(构造器除外)必须创建一个实例时,前面返回的函数就被用为新实例的构造器。
修改类的 species 是不允许的
有 Symbol.species的内置类型:
Array、ArrayBuffer 、Map、Promise、RegExp、Set、类型化数组
class MyClass {
static get [Symbol.species]() {
return this;
}
constructor(value) {
this.value = value;
}
clone() {
return new this.constructor[Symbol.species](this.value);
}
}
class MyDerivedClass1 extends MyClass {
// 空代码块
}
class MyDerivedClass2 extends MyClass {
static get [Symbol.species]() {
return MyClass;
}
}
let instance1 = new MyDerivedClass1("foo"),
clone1 = instance1.clone(),
instance2 = new MyDerivedClass2("bar"),
clone2 = instance2.clone();
console.log(clone1 instanceof MyClass); // true
console.log(clone1 instanceof MyDerivedClass1); // true
console.log(clone2 instanceof MyClass); // true
console.log(clone2 instanceof MyDerivedClass2); // false
9.10 在类的构造函数中使用new.target
调用类时不能缺少 new ,于是 new.target 属性在类构造器内部就绝不会是
undefined
class Rectangle {
constructor(length, width) {
console.log(new.target === Rectangle);
this.length = length;
this.width = width;
}
}
// new.target 就是 Rectangle
var obj = new Rectangle(3, 4);
网友评论