簡體   English   中英

ES6 Class擴展Array:ES5 Babel transile的解決方法

[英]ES6 Class extends Array: workaround for ES5 Babel transpile

我有一些繼承自Array ES6類:

class Cache extends Array {
  add(item) {
    if(!item.doNotRemove)
      this.push(item)
  }
  printLast() {
    if(this.length > 0)
      console.log(this[this.length - 1].text)
  }
}

以下代碼工作正常

const myCache = new Cache()
myCache.add({text: 'hello'})
myCache.add({text: 'world'})
myCache.add({text: '!!!', doNotRemove: true})
myCache.printLast() // world

但我無法通過Babel將其轉發給ES5(我知道存在問題 ),目前作為一種解決方法,我采用以下方法:

const CacheProto = {
  add(item) {
    if(!item.doNotRemove)
      this.push(item)
  },
  printLast() {
    if(this.length > 0)
      console.log(this[this.length - 1].text)
  }
}
function Cache() {
  return Object.assign(Object.create(Array.prototype), CacheProto)
}

這滿足上面的代碼( myCache = new Cache()等)。 但正如您所看到的,它只是一個擴展的Array實例。

這個問題

是否有可能與原始類有一個解決方法? 當然,沒有extends Array 是否可以在原型鏈上addprintLast方法以及所有Array.prototype方法,而不是實例?

我做了一個小plunker可能的研究。

如果你想要魔術.length -affecting屬性賦值( arr[42] = 21; )行為或大多數數組方法,你只需要擴展Array 如果您不需要,使用數組作為內部數據結構似乎是最簡單(和最兼容)的解決方案:

class Cache {
  constructor() {
    this._data = [];
  }

  add(item) {
    if(!item.doNotRemove)
      this._data.push(item)
  }

  printLast() {
    if(this.length > 0)
      console.log(this._data[this._data.length - 1].text)
  }
}

您可以輕松地公開.length和其他方法。


Array.prototype提取多個方法的簡單方法是:

['reduce', 'filter', 'find', ...].forEach(method => {
  Cache.prototype[method] = function(...args) {
    return this._data[method](...args);
  };
});

// Or if you want them to be non-enumerable
// (like they would if they were defined via `class` syntax)
Object.defineProperties(
  Cache.prototype,
  ['reduce', 'filter', 'find', ...].reduce((obj, method) => {
    obj[method] = {
      value: function(...args) { return this._data[method](...args); },
      enumerable: false,
      configurable: true,
      writeable: true,
    };
    return obj;
  }, {})
);

您可以使用__proto__直接操作原型,它現在也因為向后兼容性而被標准化,因此應該可以安全使用。

更多信息 - > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

編輯:像@Bergi指出的那樣,使用帶有Object.setPrototypeOf的墊片也將證明這種技術的未來。

 function Cache() { var arr = []; arr.push.apply(arr, arguments); arr.__proto__ = Cache.prototype; //if using a shim, (better option). //Object.setPrototypeOf(arr, Cache.prototype); return arr; } Cache.prototype = new Array; Cache.prototype.printLast = function () { if(this.length > 0) console.log(this[this.length - 1].text) } Cache.prototype.add = function (item) { if(!item.doNotRemove) this.push(item) } const myCache = new Cache() myCache.add({text: 'hello'}) myCache.add({text: 'world'}) myCache.add({text: '!!!', doNotRemove: true}) myCache.printLast() // world myCache.forEach(function (item) { console.log(item); }); console.log("is Array = " + Array.isArray(myCache)); 

這有點hacky,但我很確定它能滿足您的需求。

 function Cache() {} Cache.prototype = new Array; Cache.prototype.add = function(item) { if (!item.doNotRemove) { this.push(item); } }; Cache.prototype.printLast = function() { if (this.length <= 0) { return } console.log(this[this.length - 1].text); } let test = new Cache(); test.add({foo:'bar', text: 'cake' }); test.add({baz:'bat', doNotRemove: true}); test.add({free:'hugs', text: 'hello'}); test.printLast(); console.log(test); 

經過一些討論后,我能夠構建一個滿足這兩個要求的解決方案:將原始ES6類保持為新功能的狀態,並在原型上使用這個新功能,以及Array.prototype方法。

class CacheProto {
  add(item) {
    if(!item.doNotRemove)
      this.push(item)
  }
  printLast() {
    if(this.length > 0)
      console.log(this[this.length - 1].text)
  }
}

function Cache() {
  const instance = [];
  instance.push.apply(instance, arguments);
  Object.setPrototypeOf(instance, Cache.prototype);
  return instance;
}
Cache.prototype = Object.create(Array.prototype);
Object.getOwnPropertyNames(CacheProto.prototype).forEach(methodName =>
  Cache.prototype[methodName] = CacheProto.prototype[methodName]
);

CacheProto與Question中的原始類之間的唯一區別是CacheProto類不擴展Array

可以在這里獲得末端接收器。 它包含此解決方案和所有中間變體。

暫無
暫無

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

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