通过组合创建的对象上的方法无法访问所有属性
Methods on an object created via composition can't access all properties
我正在为一个产品构建一个系列的概念,其中的成员有不同的类型(accountHolder
、payingCustomer
、student
,等等)。最初我将它们构建为 FamilyMember
的子 类,但我最终得到了一些重复的代码并最终遇到了一个重大问题:我们平台的 student
也可以是唯一的 payingCustomer
和 accountHolder
.
鉴于对象组合在 JS 中被广泛吹捧为一个好主意,我决定走那条路。但是,如果 属性 属于另一个对象类型(例如 student
),则特定对象类型(例如 accountHolder
)的方法无法访问实例化对象的属性。
为了更进一步 objective 我决定使用以下代码复制该行为:
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/constructor 机制,我知道如何让它工作(例如附加到 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'
对象组合
All objects made from other objects and language primitives are composite objects.
The act of creating a composite object is known as composition.
...
Concatenation composes objects by extending an existing object with new properties, e.g., Object.assign(destination, a, b), {...a, ...b}
.
...
The Hidden Treasures of Object Composition
所以从您的模式和对 factory function 的使用来看,它看起来像串联?下面的演示是一个串联组合。请注意 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());
我正在为一个产品构建一个系列的概念,其中的成员有不同的类型(accountHolder
、payingCustomer
、student
,等等)。最初我将它们构建为 FamilyMember
的子 类,但我最终得到了一些重复的代码并最终遇到了一个重大问题:我们平台的 student
也可以是唯一的 payingCustomer
和 accountHolder
.
鉴于对象组合在 JS 中被广泛吹捧为一个好主意,我决定走那条路。但是,如果 属性 属于另一个对象类型(例如 student
),则特定对象类型(例如 accountHolder
)的方法无法访问实例化对象的属性。
为了更进一步 objective 我决定使用以下代码复制该行为:
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/constructor 机制,我知道如何让它工作(例如附加到 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'
对象组合
All objects made from other objects and language primitives are composite objects.
The act of creating a composite object is known as composition.
...Concatenation composes objects by extending an existing object with new properties, e.g.,
Object.assign(destination, a, b), {...a, ...b}
.
...
The Hidden Treasures of Object Composition
所以从您的模式和对 factory function 的使用来看,它看起来像串联?下面的演示是一个串联组合。请注意 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());