2015-09-17 80 views
24

我想寫下我的Javascript類。爲什麼JavaScript ES6不支持多構造類?

class Option { 
    constructor() { 
     this.autoLoad = false; 
    } 

    constructor(key, value) { 
     this[key] = value; 
    } 

    constructor(key, value, autoLoad) { 
     this[key] = value; 
     this.autoLoad = autoLoad || false; 
    } 
} 

我認爲如果我們可以用這種方式寫出課程會很好。 期望發生:

var option1 = new Option(); // option1 = {autoLoad: false} 
var option2 = new Option('foo', 'bar',); // option2 = {foo: 'bar'} 
var option3 = new Option('foo', 'bar', false); // option3 = {foo: 'bar', autoLoad: false} 
+0

不,它不是!我的意思是在Ecmascript 6類的編程。 – Manhhailua

+0

我的不好,抱歉:-) –

+0

@RobG:我已經更新了我的問題!請再讀一遍!謝謝! – Manhhailua

回答

20

我想寫我的Javascript類像下面

你不能以同樣的方式,你不能重載這樣的標準功能。你可以是用什麼arguments對象查詢傳遞的參數個數:

class Option { 
    constructor(key, value, autoLoad) { 
     // new Option() 
     if(!arguments.length) { 
      this.autoLoad = false; 
     } 
     // new Option(a, [b, [c]]) 
     else { 
      this[key] = value; 
      this.autoLoad = autoLoad || false; 
     } 
    } 
} 

Babel REPL Example

當然,(你更新的例子),你可以採取你沒有辦法關心數量的參數,每個單獨的值,而是否獲得通過,在這種情況下,你會這麼像:

class Option { 
    constructor(key, value, autoLoad) { 
     if(!key) { // Could change this to a strict undefined check 
      this.autoLoad = false; 
      return; 
     } 
     this[key] = value; 
     this.autoLoad = autoLoad || false; 
    } 
} 
+5

爲什麼我們堅決拒絕使用參數默認值? –

+2

@torazaburo *我們*不是。 *我*正在回答如何模擬超載的問題。我可能錯過了原始代碼的其他方面的一些優化,參數默認值是我認爲可能是多個的一個。 – CodingIntrigue

+0

使用OR雙管道'||'設置默認值通常不被認爲是好的做法。尤其是因爲es6支持它。 http://www.codereadability.com/javascript-default-parameters-with-or-operator/amp/ – GFoley83

16

你想要什麼稱爲構造函數重載。在ECMAScript中不支持這個以及更一般的function overloading的情況。

ECMAScript不像更嚴格的語言那樣處理缺少的參數。缺少參數的值保留爲undefined而不是引發錯誤。在這個範例中,很難/不可能檢測到你正在瞄準的重載函數。

慣用的解決方案是有一個函數,並讓它處理所有你需要的參數組合。對於最初的例子,你可以測試的keyvalue存在這樣的:

class Option { 
    constructor(key, value, autoLoad = false) { 
    if (typeof key !== 'undefined') { 
     this[key] = value; 
    } 
    this.autoLoad = autoLoad; 
    } 
} 
+3

如果他使用'class',他使用的是ES6。 ES6有參數默認值。使用它們。 –

+2

@torazaburo:默認值不適用於可變參數函數,但 – Bergi

4

下面是基於元數超載(數量的參數)黑客攻擊。這個想法是從多個具有不同元素的函數中創建一個函數(通過查看​​來確定)。

function overloaded(...inputs) { 
    var fns = []; 

    inputs.forEach(f => fns[f.length] = f); 

    return function() { 
    return fns[arguments.length].apply(this, arguments); 
    }; 
} 

var F = overloaded(
    function(a) { console.log("function with one argument"); }, 
    function(a, b) { console.log("function with two arguments"); } 
); 

F(1); 
F(2, 3); 

當然這需要大量的防彈和清理,但你明白了。但是,我認爲將這個應用於ES6類的構造函數並不會有太大的好處,因爲它們是不同顏色的馬。

+3

這是一個緩慢的黑客攻擊,它不是很習慣。 –

+0

不是真的推薦它。但出於好奇,你爲什麼會說這很慢,你如何定義「慣用」? –

+3

在完全解釋的環境中,可能不會有顯着差異,但對於像V8這樣的JIT編譯器,可以優化的問題與不可優化的問題之間的區別是明顯的。我不能肯定地說沒有測試,但是像這樣的動態分支關閉通常很慢。慢,雖然是主觀的(我們在這裏說話),如果它不是一個非常熱門的功能,我不會擔心。習語也是一個主觀術語,只是意味着某種東西被認爲是該語言的「最佳實踐」。例如,同步IO在JS中不是慣用的。 –

2

另一種選擇是讓你的構造方法來綁定到你的類屬性的對象:

class Option { 
 
    // Assign default values in the constructor object 
 
    constructor({key = 'foo', value, autoLoad = true} = {}) { 
 
     this.key = key; 
 
     // Or on the property with default (not recommended) 
 
     this.value = value || 'bar'; 
 
     this.autoLoad = autoLoad; 
 
     
 
     console.log('Result:', this); 
 
    } 
 
} 
 

 
var option1 = new Option(); 
 
// Logs: {key: "foo", value: "bar", autoLoad: true} 
 

 
var option2 = new Option({value: 'hello'}); 
 
// Logs: {key: "foo", value: "hello", autoLoad: true}

這是更加有用以打字稿,你可以確保類型安全與傳入的值(即key只能是一個字符串,autoLoad布爾等)。

0

從示例代碼猜測,你只需要使用默認值的參數:

class Option { 
    constructor(key = 'foo', value = 'bar', autoLoad = false) { 
     this[key] = value; 
     this.autoLoad = autoLoad; 
    } 
} 

話雖如此,另一種替代構造函數重載是使用靜態工廠。假設您希望能夠從普通參數實例化對象,從包含相同參數的哈希或甚至從JSON字符串實例化對象:

class Thing { 
    constructor(a, b) { 
     this.a = a; 
     this.b = b; 
    } 

    static fromHash(hash) { 
     return new this(hash.a, hash.b); 
    } 

    static fromJson(string) { 
     return this.fromHash(JSON.parse(string)); 
    } 
} 

let thing = new Thing(1, 2); 
// ... 
thing = Thing.fromHash({a: 1, b: 2}); 
// ... 
thing = Thing.fromJson('{"a": 1, "b": 2}'); 
相關問題