JS(原型继承)中如何获取所有祖先的方法?

How can I get all the ancestors' methods in JS (prototypal inheritance)?

我需要在 JS 中创建一个函数,从整个继承树中获取所有方法,以便为每个方法插入一个 <button>。我有这个代码

function A () {
}

A.prototype.a = function () {
    console.log('a');
}

function B () {
    this.super = A;
    this.super();
}

B.prototype = new A;
B.prototype.constructor = B;

B.prototype.b = function () {
    console.log('b');
}

function C () {
    this.super = B;
    this.super();
}

C.prototype = new B;
C.prototype.constructor = C;

C.prototype.c = function () {
    console.log('c');
}

function D () {
}

D.prototype = C;
D.prototype.constructor = D;

D.prototype.d = function () {
    console.log('d');
}

const dd = new D();

我需要一些方法来找到整个树的方法,以防我不知道一个对象有多少个祖先。例如:如果对象 C 的祖先是 A 和 B,我需要 A、B 和 C 的方法;如果 D 对象是 A-B-C 的子对象,我需要它们四个(A、B、C 和 D)的方法。我也许可以手动跟踪每种方法,以便编写一个代码来为我执行此操作,购买我需要它是动态的。

这是我正在使用的:

console.log(Object.getOwnPropertyNames(dd.__proto__).filter(function (property) {
    return (
        typeof dd.__proto__[property] === 'function' && property !== 'constructor'
    );
}))

您的设置代码有误:

变化:

D.prototype = C;

至:

D.prototype = new C;

然后要获取方法列表(即使不可枚举),进行递归调用。你甚至可以把它变成一个发电机。

为了明确方法的来源,我在它们前面加上了原型对象的名称(如 A.prototype)。您会看到,当原型链的多个级别存在同名函数时,它们将分别列出:

function * iterMethods(o) {
    if (!o || o === Object.prototype) return;
    for (let name of Object.getOwnPropertyNames(o)) {
        try {
            if (name !== "constructor" && typeof o[name] === "function") {
                yield o.constructor.name + ".prototype." + name;
            }
        } catch {}
    }
    yield * iterMethods(Object.getPrototypeOf(o));
}

// Your code:
function A () {
}

A.prototype.a = function () {
    console.log('a');
}

function B () {
    this.super = A;
    this.super();
}

B.prototype = new A;
B.prototype.constructor = B;

B.prototype.b = function () {
    console.log('b');
}

function C () {
    this.super = B;
    this.super();
}

C.prototype = new B;
C.prototype.constructor = C;

C.prototype.c = function () {
    console.log('c');
}

function D () {
}

D.prototype = new C;
D.prototype.constructor = D;

D.prototype.d = function () {
    console.log('d');
}

const dd = new D();

// The call:
console.log(Array.from(iterMethods(Object.getPrototypeOf(dd))));

使用 class ... extends 语法时,设置此原型层次结构会更容易。我也不会定义 super,因为这是一个本机可用的关键字。这是它的样子:

function * iterMethods(o) {
    if (!o || o === Object.prototype) return;
    for (let name of Object.getOwnPropertyNames(o)) {
        try {
            if (name !== "constructor" && typeof o[name] === "function") {
                yield o.constructor.name + ".prototype." + name;
            }
        } catch {}
    }
    yield * iterMethods(Object.getPrototypeOf(o));
}

// class syntax version:
class A {
    a() {
        console.log('a');
    }
}

class B extends A {
    b() {
        console.log('b');
    }
}

class C extends B {
    c() {
        console.log('c');
    }
}

class D extends C {
    d() {
        console.log('d');
    }
}

const dd = new D();

// The call:
console.log(Array.from(iterMethods(Object.getPrototypeOf(dd))));