2010-07-10 151 views
68

我需要不同的構造函數用於我的實例。什麼是常見的模式?多個構造函數的JavaScript模式

+0

請稍微具體。你想要具有不同參數集的構造函數? – galambalazs 2010-07-10 20:25:33

+2

@galambalazs是的。 – codeholic 2010-07-10 20:30:02

+0

你可以在Javascript中有多個構造函數嗎? – 2014-07-06 23:30:06

回答

22

你怎麼找到這個?

function Foobar(foobar) { 
    this.foobar = foobar; 
} 

Foobar.prototype = { 
    foobar: null 
}; 

Foobar.fromComponents = function(foo, bar) { 
    var foobar = foo + bar; 
    return new this(foobar); 
}; 
+2

return new this(foobar);不起作用。我換回新的Foobar(foobar);所有的工作都是正確的。 – isxaker 2013-10-24 07:10:55

+6

我不明白。你可以在實際使用它的地方添加代碼嗎?你每次都必須打電話給組件嗎?因爲這不是一個真正的構造函數,而是一個輔助函數。 @ bobince的回答似乎更準確。 – hofnarwillie 2014-07-03 08:33:43

+1

如果這個*做*工作,這是一個複雜的模式。 – 2015-03-09 21:54:39

3

有時,參數的默認值對於多個構造函數來說已經足夠了。如果這還不夠,我嘗試將大部分構造函數包裝到一個以後調用的init(other-params)函數中。還可以考慮使用工廠概念來創建一個可以有效創建所需其他對象的對象。

http://en.wikipedia.org/w/index.php?title=Factory_method_pattern&oldid=363482142#Javascript

+1

工廠方法感覺像是一個很好的解決方案 - 只要確保不要將其與使用單獨的工廠類相混淆,這在本用例中可能完全不相關。 – 2010-07-10 21:37:47

+1

該鏈接無處可去。該頁面上沒有Javascript錨點。 – Rob 2012-06-01 16:10:24

+1

指向舊版本。 wiki刪除了js的例子。 – eruciform 2013-08-30 04:57:47

88

JavaScript沒有函數重載,包括對方法或構造函數。

如果您希望函數的行爲有所不同,具體取決於傳遞給它的參數的數量和類型,您必須手動嗅探它們。 JavaScript會高興地調用一個函數,它的聲明數量比聲明數量多或少。

function foo(a, b) { 
    if (b===undefined) // parameter was omitted in call 
     b= 'some default value'; 

    if (typeof(a)==='string') 
     this._constructInSomeWay(a, b); 
    else if (a instanceof MyType) 
     this._constructInSomeOtherWay(a, b); 
} 

您也可以訪問arguments爲陣列狀,以獲得通過的任何進一步的論證。

如果您需要更復雜的參數,它可以是一個好主意,把一些或全部的內對象查找:

function bar(argmap) { 
    if ('optionalparam' in argmap) 
     this._constructInSomeWay(argmap.param, argmap.optionalparam); 
    ... 
} 

bar({param: 1, optionalparam: 2}) 

的Python演示瞭如何默認和命名參數可用於覆蓋大多數使用情況比函數重載更實用和優雅的方式。 JavaScript,並非如此。

+1

謝謝,這真的很好。我會說第二種選擇不僅僅在你有複雜的論證時很有用,而且還有一些簡單但很難區分的論點,例如,支持'MyObj({foo:「foo」})'加'MyObj({bar:「bar」})''。 MyObj有兩個構造函數 - 但都帶有一個參數,它是一個字符串:-) – 2012-11-15 11:06:58

+1

您是否可以爲此特定示例添加更多示例代碼。 – 2014-07-06 23:31:36

+0

Hi @DougHauf,Crockford的書'JavaScript:The Good Parts'有一個關於這個命名爲'對象說明符'的部分,大量的例子在線提及它。 – 2017-04-24 09:42:31

9

與eruciform的回答進一步說,你可以鏈接您的通話new到您init方法。

function Foo() { 
    this.bar = 'baz'; 
} 

Foo.prototype.init_1 = function (bar) { 
    this.bar = bar; 
    return this; 
}; 

Foo.prototype.init_2 = function (baz) { 
    this.bar = 'something to do with '+baz; 
    return this; 
}; 

var a = new Foo().init_1('constructor 1'); 
var b = new Foo().init_2('constructor 2'); 
+0

所以基本上你在這裏做的是取對象Foo,然後用原型函數調用init_1和init_2參數。你的init_1和init_2是否應該有這個詞的功能。 – 2014-07-06 23:38:33

+0

確實在第一個Foo()後面必須有一個分號。 – 2014-07-06 23:40:31

+0

謝謝道格,我做了改變。 – laughingbovine 2014-10-08 22:53:14

10

不喜歡做手工,如bobince的答案,所以我只是完全扯下jQuery的插件選項模式。

這裏的構造函數:

//default constructor for Preset 'class' 
function Preset(params) { 
    var properties = $.extend({ 
     //these are the defaults 
     id: null, 
     name: null, 
     inItems: [], 
     outItems: [], 
    }, params); 

    console.log('Preset instantiated'); 
    this.id = properties.id; 
    this.name = properties.name; 
    this.inItems = properties.inItems; 
    this.outItems = properties.outItems; 
} 

這裏的實例不同的方式:

presetNoParams = new Preset(); 
presetEmptyParams = new Preset({}); 
presetSomeParams = new Preset({id: 666, inItems:['item_1', 'item_2']}); 
presetAllParams = new Preset({id: 666, name: 'SOpreset', inItems: ['item_1', 'item_2'], outItems: ['item_3', 'item_4']}); 

及這裏的做什麼:

presetNoParams 
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]} 

presetEmptyParams 
Preset {id: null, name: null, inItems: Array[0], outItems: Array[0]} 

presetSomeParams 
Preset {id: 666, name: null, inItems: Array[2], outItems: Array[0]} 

presetAllParams 
Preset {id: 666, name: "SOpreset", inItems: Array[2], outItems: Array[2]} 
+0

我在node.js中也使用了相同的模式:https://www.npmjs.com/package/extend – 2016-06-17 16:37:26

1

所以,是像以前那樣措辭,多種解決方案,你在日常生活中看到的一般是靜態方法:

Date.UTC("some params"); 

這並不是雖然適當的構造,這是雖然

function someObject(a,b,c,d,e,f) { 
a = a || "default"; 
b = b || "defaultb" 
} 

可以去打字稿或transpile它ES5?

constructor(a:string, b = "default value", c:number? //optional 
) { 

} 
2

這是在Programming in HTML5 with JavaScript and CSS3 - Exam Ref中爲多個構造函數給出的示例。

function Book() { 
    //just creates an empty book. 
} 


function Book(title, length, author) { 
    this.title = title; 
    this.Length = length; 
    this.author = author; 
} 

Book.prototype = { 
    ISBN: "", 
    Length: -1, 
    genre: "", 
    covering: "", 
    author: "", 
    currentPage: 0, 
    title: "", 

    flipTo: function FlipToAPage(pNum) { 
     this.currentPage = pNum; 
    }, 

    turnPageForward: function turnForward() { 
     this.flipTo(this.currentPage++); 
    }, 

    turnPageBackward: function turnBackward() { 
     this.flipTo(this.currentPage--); 
    } 
}; 

var books = new Array(new Book(), new Book("First Edition", 350, "Random")); 
+0

和不變性?使用原型將屬性公開,對嗎? – 2017-06-15 22:29:36