![](/img/trans.png)
[英]How a super function can access another super function inside a child class?
[英]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();
基本上,箭頭函數維護this
和super
上下文,這與文字function
關鍵字不同
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.