2015-10-13 128 views
4

嘗試ES6並試圖創建一個具有靜態屬性和功能的類來解析。然後我想擴展我解析的每種不同類型的基本解析器。不知道我是否在做反模式,但我無法重寫靜態屬性。Javascript es6覆蓋靜態屬性

這是我的基地解析器

class Module { 

    static name = 'Default Module' 
    static version = {major:10000, minor: 10000} 

    static checkVersion({majorVersion = 10000, minorVersion = 10000}) { 
    if(this.version.major !== majorVersion || this.version.minor > minorVersion) { 
     throw `${this.name} requires version ${this.version.major}.${this.version.minor} got ${majorVersion}.${minorVersion}`; 
    } 
    } 

    static parse(data) { 
    try { 
     this.checkVersion(data); 
     return this.internalParser(data); 

    } catch (e) { 
     throw e; 
    } 
    } 

    static internalParser(data) { 
    throw `${this.name} has no parser implemented`; 
    } 
} 

然後我想擴展這樣

class ExtendedModule extends Module { 
    static name = 'Extended'; 
    static version = {major: 1, minor:0} 

    static internalParser(data) { 
    //Some stuff 
    } 
} 

但在節點與巴貝爾編譯時,我得到

true; if ('value' in descriptor) descriptor.writable = true; Object.defineProp 
                    ^
TypeError: Cannot redefine property: name 
    at Function.defineProperty (native) 

任何人都得到一個線索如果這甚至可能或只是明顯錯誤?

+3

這不是ES6。 ES6沒有類屬性初始值設定項。 –

+2

另外,'Module.name'是'「Module」(它仍然是一個命名的構造函數)。你不能在其上放置另一個'.name'。 – Bergi

+0

@Bergi雖然它可能會導致框架或類似的問題,例如爲了創建一些調試輸出而試圖讀取名稱,您絕對可以在其上放置另一個'.name'。對Javascript來說這很棒:你可以很容易地破解事情,但你仍然可以做到。 ;) – cepharum

回答

6

類是函數(在transpiled碼),並在定義靜態屬性,它們被直接連接到類的構造函數,所以:

class Foo { 
    static name = 'foo'; 
} 

相同做

function Foo(){} 
Object.defineProperty(Foo, 'name', { 
    configurable: true, 
    writable: true 
    value: 'foo' 
}); 

如果您在瀏覽器中嘗試這樣做,您會收到錯誤,這正是您所看到的。這是因爲該功能已經有一個名爲name的屬性,它是Foo。在ES5中,名稱屬性爲configurable: false,所以您嘗試執行的操作不起作用,因此出現TypeError: Cannot redefine property: name錯誤,您需要將靜態重命名爲其他內容。

在ES6中,name實際上是configurable: true所以你試圖做的事情最終會奏效,但瀏覽器需要先更新自己。

這裏更大的問題是爲什麼你需要使用一個類。如果你正在使用所有的靜態變量,那麼你可以直接使用一個不需要類直接導出所有東西的模塊,然後包裝它。它有一個導出創建功能的模塊,可以傳遞一個innerParser方法或其他東西。你目前的代碼方式是使用類。

+0

謝謝多數民衆贊成在一個更好的解決方案:)我剛剛發現了關於類,並想嘗試和使用them.Thought它會更容易閱讀 –

+0

你有錯誤的代碼 它應該'defineProperty'不'definedProperty' – bumbeishvili

+1

@bumbeishvili良好的電話,修正了錯字。 – loganfsmyth

1

您可以嘗試使用靜態吸氣實現代碼的最初打算層次:

class Module { 
    static get name() { return "Default Module"; } 
    static get version() { return {major:10000, minor: 10000}; } 

    static parse() { 
     console.log(this.name); 
    } 
} 

class ExtendedModule extends Module { 
    static get name() { return "Extended"; } 
    static get version() { return {major:1, minor: 0}; } 
} 

ExtendedModule.parse(); 

使用BabelJS這成爲

"use strict"; 

var _createClass = function() { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 

var Module = function() { 
    function Module() { 
     _classCallCheck(this, Module); 
    } 

    _createClass(Module, null, [{ 
     key: "parse", 
     value: function parse() { 
      console.log(this.name); 
     } 
    }, { 
     key: "name", 
     get: function get() { 
      return "Default Module"; 
     } 
    }, { 
     key: "version", 
     get: function get() { 
      return { major: 10000, minor: 10000 }; 
     } 
    }]); 

    return Module; 
}(); 

var ExtendedModule = function (_Module) { 
    _inherits(ExtendedModule, _Module); 

    function ExtendedModule() { 
     _classCallCheck(this, ExtendedModule); 

     return _possibleConstructorReturn(this, (ExtendedModule.__proto__ || Object.getPrototypeOf(ExtendedModule)).apply(this, arguments)); 
    } 

    _createClass(ExtendedModule, null, [{ 
     key: "name", 
     get: function get() { 
      return "Extended"; 
     } 
    }, { 
     key: "version", 
     get: function get() { 
      return { major: 1, minor: 0 }; 
     } 
    }]); 

    return ExtendedModule; 
}(Module); 

ExtendedModule.parse(); 

運行代碼,它是在顯示

Extended 

JS控制檯。