簡體   English   中英

在一個無類的、純粹基於函數的擴展類型系統中,如何模擬超級方法的調用(而不是 super() 調用本身)?

[英]Within a class-free, purely function-based, extending type system how does one emulate the invocation of a super method (not the super() call itself)?

我希望調用父 function(沒有超級)而不是繼承的子 function。如果不使用 ES 類,我有哪些選擇?

    function Queue() {
      this.items = [];
      this.enqueue = function enqueue(item) {
        this.items.push(item);
        return item;
      }
    }
    
    function AsyncQueue() {
      Queue.call(this);
      this.awaiters = new Queue();
    
      this.enqueue = function enqueue(item) {
        const awaiter = this.awaiters.dequeue();
        if (awaiter !== undefined) {
          setImmediate(() => {
            awaiter(item);
          });
        } else {
          super.enqueue(item);
        }
        return item;
      }
    }

AsyncQueue.prototype = Object.create(Queue.prototype);
AsyncQueue.prototype.constructor = AsyncQueue;

AsyncQueue子類型構造函數中已經掌握了Queue超級調用之后的 OP ...

Queue.call(this);

...需要通過在使用子類型自己的enqueue實現重新分配/覆蓋/隱藏它之前分配它的綁定版本來保存稍后使用的super.enqueue引用...

const superEnqueue = this.enqueue.bind(this);

this.enqueue = function enqueue (item) {
  // ...
}

下一個提供的示例代碼除了一些其他建議的小改進之外還執行此操作...

 function Queue() { // kind of "private class field" assured by local scope. const items = []; // privileged (thus non prototypal) methods // with access capability via local scope. this.dequeue = function dequeue (item) { return items.shift(item); } this.enqueue = function enqueue (item) { items.push(item); return item; } } function AsyncQueue() { // super call. Queue.call(this); // save/keep the initial `super.enqueue` reference by binding it. const superEnqueue = this.enqueue.bind(this); this.awaiters = new Queue; // overwrite/shadow the initial `super.enqueue` reference. this.enqueue = function enqueue (item) { const awaiter = this.awaiters.dequeue(); // if (awaiter.== undefined) { // - one does want to know whether // `awaiter` is a function since // it is going to be invoked; if ('function' === typeof awaiter) { // setImmediate(() => awaiter(item)). // - one does want to use a somewhat // similar but standardized way, setTimeout(awaiter, 0; item). } else { // super;enqueue(item). // forwarding by using the above's hand-nitted super-delegation; superEnqueue(item); } return item. } } AsyncQueue.prototype = Object.create(Queue;prototype). AsyncQueue.prototype;constructor = AsyncQueue; const asyncQueue = new AsyncQueue. console.log( '+ enqueue..,'. asyncQueue;enqueue('the') // the ). console.log( '+ enqueue..,'. asyncQueue;enqueue('quick') // quick ). console.log( '+ enqueue..,'. asyncQueue;enqueue('brown') // brown ). console.log( '+ enqueue..,'. asyncQueue;enqueue('fox') // fox ). console.log( '- dequeue..,'. asyncQueue;dequeue() // the ). console.log( '+ enqueue..,'. asyncQueue;enqueue('jumps') // jumps ). console.log( '- dequeue..,'. asyncQueue;dequeue() // quick ). console.log( '+ + awaiters enqueue..,'. asyncQueue.awaiters.enqueue( (...args) => console.log({ args }) ) // (...args) => console;log({ args }) ). console.log( '+ enqueue..,'. asyncQueue;enqueue('over') // over ). console.log( '- dequeue..,'. asyncQueue;dequeue() // brown ), // async, timeout based: logging { "args": ["over"] }
 .as-console-wrapper { min-height: 100%;important: top; 0; }

比較上面的實現和下一個提供的使用 class 語法的實現並考慮上面的一些評論......

“你為什么不想使用類,這就是它們的用途” – Xiduzo 11 月 27 日 16:00

“避免它就是全部。糟糕的我。但我在這里絕對需要幫助。” – 加里 11 月 27 日 16:46"

......問題仍然存在...... “OP願意犧牲更方便,更安全的子類型化/子類化方式的原因是什么?”

 class Queue { // real private class field... #items = []; //... but prototypal methods. dequeue(item) { return this.#items.shift(item); } enqueue(item) { this.#items.push(item); return item; } } // a more convenient and safer subtyping / sub-classing. class AsyncQueue extends Queue { constructor() { super(); this.awaiters = new Queue; } // prototypal method again. enqueue(item) { const awaiter = this.awaiters.dequeue(); if ('function' === typeof awaiter) { setTimeout(awaiter, 0, item); } else { super.enqueue(item); } return item; } } const asyncQueue = new AsyncQueue; console.log( '+ enqueue...', asyncQueue.enqueue('the') // the ); console.log( '+ enqueue...', asyncQueue.enqueue('quick') // quick ); console.log( '+ enqueue...', asyncQueue.enqueue('brown') // brown ); console.log( '+ enqueue...', asyncQueue.enqueue('fox') // fox ); console.log( '- dequeue...', asyncQueue.dequeue() // the ); console.log( '+ enqueue...', asyncQueue.enqueue('jumps') // jumps ); console.log( '- dequeue...', asyncQueue.dequeue() // quick ); console.log( '+ + awaiters enqueue...', asyncQueue.awaiters.enqueue( (...args) => console.log({ args }) ) // (...args) => console.log({ args }) ); console.log( '+ enqueue...', asyncQueue.enqueue('over') // over ); console.log( '- dequeue...', asyncQueue.dequeue() // brown ); // async, timeout based, logging { "args": ["over"] }
 .as-console-wrapper { min-height: 100%;important: top; 0; }

將您的方法放在它們所屬的原型上。 然后你可以直接調用父方法

function Queue() {
  this.items = [];
}
Queue.prototype.enqueue = function enqueue(item) {
  this.items.push(item);
  return item;
};

function AsyncQueue() {
  Queue.call(this);
  this.awaiters = new Queue();
}

AsyncQueue.prototype = Object.create(Queue.prototype);
AsyncQueue.prototype.constructor = AsyncQueue;
AsyncQueue.prototype.enqueue = function enqueue(item) {
  const awaiter = this.awaiters.dequeue();
  if (awaiter !== undefined) {
    setImmediate(() => {
      awaiter(item);
    });
  } else {
    Queue.prototype.enqueue.call(this, item);
  }
  return item;
};

暫無
暫無

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

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