读《深入理解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(
唯一能避免调用 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(
若多个混入对象拥有相同的属性,则只有最后添加 的属性会被保留
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