继承

  • 静态方法不在实例化的对象上,所以 new 出来的对象上是没有静态方法的
  • 普通属性的继承,在 function B{ }调用 A.call(this, name)
  • 普通方法的继承
// 方案一
B.prototype = Object.create(A.prototype) // 原型继承,创建一个空对象,并把空对象的 __proto__ 设置为 A.prototype
Object.defineProperty(B.prototype, "constructor", {
    value: B,
    enumerable: false
})
// 方案二
Object.setPrototypeOf(B.prototype, A.prototype)
  • 以上的方法在继承层级大于二的时候有问题
  • 关于静态属性、方法的继承可以利用 B.__proto__ = A 实现

类的继承

class A {
    constructor(name) {
        this.name = name
    }
    sing() {
        return `${this.name}在唱歌`
    }
}
class B extends A {
    constructor(name, age) {
        super(name)
        this.age = age
    }
    sing() {
        return `${this.age}岁的${super.sing()}`
    }
}

原型链的继承

function A(name) {
    this.name = name
}
A.prototype.sing = function () {
    return `${this.name}在唱歌`
}
function B(name, age) {
    A.call(this, name) //其实等于在 B 添加了 name 属性
    this.age = age
}
// 方案一
B.prototype = Object.create(A.prototype) // 原型继承,创建一个空对象,并把空对象的 __proto__ 设置为 A.prototype
Object.defineProperty(B.prototype, "constructor", {
    value: B,
    enumerable: false
})
B.prototype.sing = function () {
    return `${this.age}岁的${A.prototype.sing.call(this)}`
}
// 方案二
Object.setPrototypeOf(B.prototype, A.prototype)
// 方案三
B.prototype.__proto__ = A.prototype

动态与静态

原型实现

"use strict"
// 动态
function Web() {
    this.aaa = "this is aaa" //普遍属性
}
Web.prototype.bbb = function () {
    console.log(this)
    return "this is bbb" //普遍方法
}
Web.prototype.ccc = function () {
    return 'cccFun:' + this.aaa //普遍方法里调用普通属性
}
Web.prototype.ddd = function () {
    return 'dddFun:' + Web.eee //普通方法里调用静态属性
}
// 静态
Web.eee = "this is eee" // 静态属性
Web.fff = function () {
    console.log(this)
    return "this is fff" // 静态方法
}
Web.ggg = function () {
    return 'gggFun:' + this.aaa //静态方法里调用普通属性
    // !!!错误的调用,因为没有 new 所以当前的 this 是指向 Web 对象,而不是 Web 实例化的对象
}
Web.hhh = function () {
    return 'hhhFun:' + this.eee //静态方法里调用静态属性
}
Web.iii = function () {
    return 'iiiFun:' + Web.eee //静态方法里调用静态属性
}

类实现

"use strict"
class Html {
    aaa = "this is aaa" //普遍属性
    bbb() {
        return "this is bbb"//普遍方法
    }
    ccc() {
        return 'cccFun:' + this.aaa //普遍方法里调用普通属性 
    }
    ddd() {
        return 'dddFun:' + Html.eee //普通方法里调用静态属性
    }
    // 静态
    static eee = "this is eee" // 静态属性
    static fff() {
        return "this is fff" // 静态方法
    }
    static ggg() {
        return 'gggFun:' + this.aaa
        // !!!错误的调用,因为没有 new 所以当前的 this 是指向 Web 对象,而不是 Web 实例化的对象
    }
    static hhh() {
        return 'hhhFun:' + this.eee //静态方法里调用静态属性
    }
    static iii() {
        return 'iiiFun:' + Html.eee //静态方法里调用静态属性
    }
}

访问/获取器

"use strict"
class Requset {
    constructor(host) {
        this.data = {}
    }
    set host(url) {
        if (!/^https?:\/\//i.test(url)) {
            throw new Error("地址错误")
        }
        this.data.host = url
    }
    get host() {
        return this.data.host
    }
}

访问权限

受保护的:Symbol 实现

"use strict"
const protecteds = Symbol()
class Requset {
    constructor(host) {
        this[protecteds] = {}
        this.host = host
    }
    set host(url) {
        if (!/^https?:\/\//i.test(url)) {
            throw new Error("地址格式错误")
        }
        this[protecteds].host = url
    }
    get host() {
        return this[protecteds].host
    }
}

受保护的:WeakMap 实现

"use strict"
const protecteds = new WeakMap()
class Requset {
    constructor(host) {
        this.host = host
    }
    set host(host) {
        if (!/^https?:\/\//i.test(host)) {
            throw new Error("地址错误")
        }
        protecteds.set(this, { ...protecteds.get(this), host })
    }
    get host() {
        return protecteds.get(this).host
    }
}

私有的:# 实现

"use strict"
class Requset {
    #host = ""
    constructor(host) {
        this.#host = host
        this.#check(this.#host)
    }
    set host(host) {
        if (!/^https?:\/\//i.test(host)) {
            throw new Error("地址错误")
        }
        this.#check(host)
        this.#host = host
    }
    get host() {
        return this.#host
    }
    #check = (name) => {
        if (name.length < 15) {
            throw new Error("名字长度不能小于五位")
        }
    }
}

mixin 混合模式

就是在类的 .portotype 上追加另一个对象的所有属性

"use strict"
Object.assign(B.prototype, A)