簡體   English   中英

如何在內部生成器函數內部訪問超類方法?

[英]How to access super class method inside of internal generator function?

看看這些基類和派生類,它們只是具有“名稱”作為屬性的簡單類:

class Base {
    constructor(name) {
        this.name = name;
    }
    printName() {
        console.log("Base: " + this.name);
    }
}

class Derieved extends Base {
    constructor(name) {
        super(name);
    }
    // Override
    printName() {
        // IIFE.
        (function() {
            super.printName();  // Can't use super here
        })();

        console.log("Derived: " + this.name);
    }
}

var obj = new Derieved('John');
obj.printName();

我想從Derieved :: printName調用Base :: printName。 但是由於某些原因,我必須在Derieved :: printName的內部函數中調用。

但是運行上面的代碼,它將失敗並顯示:

語法錯誤:“ super”關鍵字在此意外

如果我將parent方法的引用保存到變量中,則可以調用但無法訪問任何屬性,它表示未定義。

TypeError:無法讀取未定義的屬性“名稱”

我只是寫了內部函數只是普通函數,但是實際上它是生成器函數,所以我不能使用箭頭函數:

get(match: T, options: IQueryOptions|void): Promise<Array<Object>|Error> {
    const superGet = super.get;

    return new Promise((resolve, reject) => {
        co(function*() {
            try {
                    // I need to invoke parent's get method here!!
                const accounts = yield superGet(match, options);

                ... // do something with accounts

                resolve(accounts);
            }
            catch(err) {
                ...
            }
        });
    });
}

有沒有辦法做到這一點? 為什么我不能將對父方法的引用保存到變量中?

只能從子方法訪問super ,而不能從該方法內部調用的函數范圍訪問。

生成器函數仍然是函數,並且支持綁定。 這將導致綁定函數無法通過其簽名識別為生成器函數,但是只要協程庫支持通用迭代器( co確實如此),就可以了。

所以基本上是

get(...) {
    const superGet = super.get;

    return new Promise((resolve, reject) => {
        co(function*() {
              ...
              const accounts = yield superGet.call(this, match, options);
              ...
        }.bind(this));
    });
}

甚至更好:

get(...) {
    const superGet = super.get.bind(this);

    return new Promise((resolve, reject) => {
        co(function*() {
              ...
              const accounts = yield superGet(match, options);
              ...
        });
    });
}

這里有幾處可以改進的地方。 第一個是它使用promise構造函數的反模式。 co已經返回了承諾,因此無需將其與new Promise包裝在一起。

另一件事是,為了無縫繼承,將生成器方法和承諾方法分開是有益的。 co支持委派的yield s,這使得這更加容易:

class Base {
  get(...args) {
    return co(this._get.bind(this, ...args));
  }

  * _get(...) { ... }
}

class Child extends Base {
  * _get(...) {
    ...
    const accounts = yield* super._get(match, options);
    ...
  }
}

TypeScript和Babel都支持ES2017 async..await ,並且能夠在ES6目標輸出中回退到co like生成協程。 這使得co在編譯的JS項目中毫無用處,上面的代碼變為:

class Child extends Base {
  async get(...) {
    ...
    const accounts = await super.get(match, options);
    ...
  }
}

顯然,無論如何,您都會為類型注釋使用一些編譯器。 在那種情況下,解決方案是只刪除co庫和生成器,並改用適當的現代async / await語法,該語法受TypeScript,Babel和本機nodejs支持:

async get(match: T, options: IQueryOptions|void): Promise<Array<Object>|Error> {
    try {
        const accounts = await super.get(match, options);
        … // do something
        return accounts;
    }
    catch(err) {
        …
    }
}

super將會在這里開箱即用。

箭頭功能可以解救!

 class Base { constructor(name) { this.name = name; } printName() { console.log("Base: " + this.name); } } class Derieved extends Base { constructor(name) { super(name); } // Override printName() { // IIFE (() => { super.printName(); // Can't use super here })(); console.log("Derived: " + this.name); } } var obj = new Derieved('John'); obj.printName(); 

基本上,箭頭函數維護thissuper上下文,這與文字function關鍵字不同

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM