读《深入理解ES6》


读<<深入理解ES6>>

1 类

1.1 声明

class PersonClass {
// 等价于 PersonType 构造器
constructor(name) {
this.name = name;
}
// 等价于 PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
}
let person = new PersonClass("Nicholas");
person.sayName(); // 输出 "Nicholas"
  • PersonClass 声明实际上创建了一个拥有 constructor 方法及其行为的函数

  • typeof PersonClass 会得到 "function" 结果的原因

  • 类的声明不会被提升

  • 类声明中的所有代码自动运行在严格模式, 无法退出

  • 类的方法不可枚举

     

1.2 匿名类声明

let PersonClass = class {
// 等价于 PersonType 构造器
constructor(name) {
this.name = name;
}
// 等价于 PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
};
let PersonClass = class PersonClass2 {
// 等价于 PersonType 构造器
constructor(name) {
this.name = name;
}
// 等价于 PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
};

上文第一个类声明相当于下文内外的类名都定义为PersonClassType

第二个相当于外面的类名定义为PersonClass, 里面的定义为PersonClass2

ES5实现的类声明

let PersonType2 = (function() {
"use strict";
const PersonType2 = function(name) {
// 确认函数被调用时使用了 new
if (typeof new.target === "undefined") {
throw new Error("Constructor must be called with new.");
}
this.name = name;
}
Object.defineProperty(PersonType2.prototype, "sayName", {
value: function() {
// 确认函数被调用时没有使用 new
if (typeof new.target !== "undefined") {
throw new Error("Method cannot be called with new.");
}
console.log(this.name);
},
enumerable: false,
writable: true,
configurable: true
});
return PersonType2;
}());

JS的函数就是一级公民, 这让JS独一无二

即能作参数、函数返回值、给变量赋值

1.3 访问器属性

class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}

1.4 注入方法名

普通方法

let methodName = "sayName";
class PersonClass {
constructor(name) {
this.name = name;
}
[methodName]() {
console.log(this.name);
}
}
?

访问器属性

let propertyName = "html";
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get [propertyName]() {
return this.element.innerHTML;
}
set [propertyName](value) {
this.element.innerHTML = value;
}
}

1.5 生成器方法(迭代器)

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);
}

1.6 静态成员

class PersonClass {
// 等价于 PersonType 构造器
constructor(name) {
this.name = name;
}
static create(name) {
return new PersonClass(name);
}
}

1.7 继承

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);
}
}

派生类不指定构造器则有如下默认构造器

class Square extends Rectangle {
// 没有构造器
}
// 等价于:
class Square extends Rectangle {
constructor(...args) {
super(...args);
}
}
?

唯一能避免调用 super() 的办法,是从类构造器中返回一个对象。

静态成员可被继承, 行为和基类中一致

1.8 从函数中派生类

对改造旧代码有用

function Rectangle(length, width) {
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function() {
return this.length * this.width;
};
class Square extends Rectangle {
constructor(length) {
super(length, length);
}
}

混入(类似接口)

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;
}
}

若多个混入对象拥有相同的属性,则只有最后添加 的属性会被保留

ES5时实现的模拟类的派生类的构造器执行顺序是先派生类,后基类

ES6改为先基类

1.9 Symbol.species

Symbol.species 属性会导致任意能返回内置对象实例的方法,在派生类上却会自动返 回派生类的实例

如: 继承了 Array 的派生类 MyArray ,诸如 slice() 之 类的方法都会返回 MyArray 的实例

使用Symbol.species

class MyClass {
static get [Symbol.species]() {
return this;
}
constructor(value) {
this.value = value;
}
clone() {
return new this.constructor[Symbol.species](this.value);
}
}

可以自定义get [Symbol.species]方法从而改变上述行为

如:

class MyArray extends Array {
static get [Symbol.species]() {
return Array;
}
}
?

一旦想在类中使用this.constructor方法就应当定义get [Symbol.species]方法

1.10 new.target

可用在定义抽象基类

class Shape {
constructor() {
if (new.target === Shape) {
throw new Error("This class cannot be instantiated directly.")
}
}
}

 

中文时输入英文标点

https://blog.csdn.net/qq_38526952/article/details/89202555