[英]Methods on an object created via composition can't access all properties
我正在為產品構建家庭的概念,成員具有不同的類型( accountHolder
、 payingCustomer
、 student
等)。 最初我將這些作為FamilyMember
子類FamilyMember
,但我最終得到了一些重復的代碼,最終遇到了一個重大問題:我們平台的student
也可以是唯一的payingCustomer
和accountHolder
。
鑒於對象組合在 JS 中被廣泛吹捧為一個好主意,我決定走這條路。 但是,特定對象類型(例如accountHolder
)的方法不能訪問實例化對象的屬性,如果該屬性屬於另一個對象類型(例如student
)。
為了使這更客觀,我決定使用以下代碼復制行為:
const person = (props) => {
let state = {
name: props.name,
}
state.isOfAge = () => {
// state.isAdult is always undefined because
// isAdult doesn't exist in this object
return state.isAdult === true
}
return state
}
const adult = (props) => {
return {
isAdult: true,
}
}
const factory = (props) => {
return Object.assign({}, person(props), adult(props))
}
const john = factory({
name: 'John',
})
console.clear()
console.log(john) // { isAdult: true, name: "John", isOfAge... }
console.log(john.isOfAge()) // false
我期待john
的方法isOfAge
能夠訪問屬性isAdult
,因為它在對象中。 但是,從概念上講,我理解為什么它不起作用: isOfAge
是一種state
方法,而不是生成的adult
實例。
如果我使用類,甚至是傳統的原型/構造器機制,我知道如何使其工作(例如附加到prototype
)。 對於對象組合,我不知道如何到達那里,可能是由於缺乏 FP 的經驗。
謝謝您的幫助!
您可以在isOfAge
使用this
而不是state
。 這樣,當方法isOfAge
被調用時, this
將被推斷,它將被綁定到它被調用的任何對象。 但是,您必須使用常規函數而不是箭頭函數才能工作(箭頭函數沒有this
):
const person = (props) => { let state = { name: props.name, } state.isOfAge = function() { // use a regular function return this.isAdult === true // use this here instead of state } return state } const adult = (props) => { return { isAdult: true, } } const factory = (props) => { return Object.assign({}, person(props), adult(props)) } const john = factory({ name: 'John', }) console.log(john); console.log(john.isOfAge()); // returns 'true' because 'this' inside 'isOfAge' will be 'john'
串聯通過使用新屬性擴展現有對象來組合對象,例如
Object.assign(destination, a, b), {...a, ...b}
。
...
對象組合的隱藏寶藏
所以從你的模式和工廠函數的使用來看,它看起來像連接? 下面的演示是一個串聯組合。 請注意圍繞payment
括號的括號:
const payment = (status) => ({...})
這允許payment
作為對象而不是函數返回。 如果您的數據更靈活一些,您將需要更少的方法。 name: string
和age: number
是我使用的屬性,認為它實用,或者在你的情況下name: string
和adult: boolean
。
const payment = (status) => ({ adult: () => status.age > 17 ? true : false, account: () => status.adult() ? 'holder' : 'student' }); const member = (name, age) => { let status = { name, age }; return Object.assign(status, payment(status)); }; const soze = member('Kaiser Soze', 57); console.log(soze); console.log(soze.adult()); console.log(soze.account()); const jr = member('Kaiser Soze Jr.', 13); console.log(jr); console.log(jr.adult()); console.log(jr.account());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.