Why Are Higher Order Functions Hiding My Es6 Class Properties?
Solution 1:
At new enhancedClass('Edgar')
, this happens:
lastNameClass
's constructor callssuper
middleNameClass
's constructor callssuper
Person
's constructor callssuper
firstNameClass
doesthis.firstName = 'Edgar'
- Return to
Person
, which callsgetNames
- Return to
middleNameClass
, which doesthis.middleName = 'Allan'
- Return to
lastNameClass
, which doesthis.lastName = 'Poe'
Calling getNames
afterwards should work. Same thing would've happened if you used extend
every time.
Solution 2:
This isn't an answer to your question but maybe it's a solution to your problem
JavaScript doesn't have multiple inheritance but luckily for you functional programming has nothing to do JavaScript's class system, object prototypes, or other object-oriented concepts. Functional programming is all about functions!
We begin writing our inheritable modules with some functions
// module 1consthasFirstName = (firstName = "") => o =>
{
field (o, 'firstName', firstName)
}
// module 2consthasMiddleName = (middleName = "") => o =>
{
field (o, 'middleName', middleName)
}
// module 3consthasLastName = (lastName = "") => o =>
{
field (o, 'lastName', lastName)
}
We haven't defined field
yet, but don't worry. Let's look at a somewhat more involved module next
// module 4constnameable = (first, middle, last) => o =>
{
inherit (o, hasFirstName (first))
inherit (o, hasMiddleName (middle))
inherit (o, hasLastName (last))
method (o, 'getFullName', (self) =>`${self.firstName}${self.middleName}${self.lastName}`)
method (o, 'sayHelloTo', (self, other) =>`Hello ${other.getFullName ()}, my name is ${self.getFullName ()}`)
}
OK, so now we can see how some modules can be composed of other modules. Before we look at inherit
and method
, let's see how we'd use our module
constPerson = (first, middle, last) =>
Obj (self => {
inherit (self, nameable (first, middle, last))
})
So maybe you're annoyed that I keep making stuff up in each new code paste, but this is a very powerful practice called wishful thinking
"Wishful Thinking" is a very powerful programming practice:
Before implementing a component you write some of the code that actually uses it. This way you discover what functions with what parameters you really need, which leads to a very good interface. You will also have some good test code for your component.
The idea is based on the fact that an interface's purpose is to simplify the code that uses the component, not to simplify the code that implements it.
Exercising this practice, we wished up this imaginary object system based on what we need it to do - not based on what JavaScript's object system is capable of.
Of course we expect that using our Person
will be straightforward
const p1 =
Person ('Augusta', 'Ada', 'King-Noel', 166)
const p2 =
Person ('Gerald', 'Jay', 'Sussman', 71)
console.log (p1.sayHelloTo (p2))
// Hello Gerald Jay Sussman, my name is Augusta Ada King-Noel
And here's the dependencies: What I want you to see here is that no class
or even this
is used. So even if JavaScript didn't have a native object system, this demonstrates you could make your own
constObj = (f, instance = {}) =>
(f (instance), instance)
constinherit = (o, f) =>
Object.assign (o, f (o))
constfield = (o, name, value) =>
Object.assign (o, { [name]: value })
constmethod = (o, name, f) =>
Object.assign (o, { [name]: (...xs) => f (o, ...xs) })
Full program demonstration
// DIY class systemconstObj = (f, instance = {}) =>
(f (instance), instance)
constinherit = (o, f) =>
Object.assign (o, f (o))
constfield = (o, name, value) =>
Object.assign (o, { [name]: value })
constmethod = (o, name, f) =>
Object.assign (o, { [name]: (...xs) => f (o, ...xs) })
// module 1consthasFirstName = (firstName = "") => o =>
{
field (o, 'firstName', firstName)
}
// module 2consthasMiddleName = (middleName = "") => o =>
{
field (o, 'middleName', middleName)
}
// module 3consthasLastName = (lastName = "") => o =>
{
field (o, 'lastName', lastName)
}
// module 4constnameable = (first, middle, last) => o =>
{
inherit (o, hasFirstName (first))
inherit (o, hasMiddleName (middle))
inherit (o, hasLastName (last))
method (o, 'getFullName', (self) =>`${self.firstName}${self.middleName}${self.lastName}`)
method (o, 'sayHelloTo', (self, other) =>`Hello ${other.getFullName ()}, my name is ${self.getFullName ()}`)
}
// Person classconstPerson = (first, middle, last) =>
Obj (self => {
inherit (self, nameable (first, middle, last))
})
// democonst p1 =
Person ('Augusta', 'Ada', 'King-Noel')
const p2 =
Person ('Gerald', 'Jay', 'Sussman')
console.log (p1.sayHelloTo (p2))
// Hello Gerald Jay Sussman, my name is Augusta Ada King-Noel
Our Person class can obviously define its own fields and methods as well
constdateDiff = (d1, d2) =>
Math.abs (d1 - d2) / 1000 / 60 / 60 / 24 / 365 >> 0constPerson = (first, middle, last, birthdate = newDate) =>
Obj (self => {
inherit (self, nameable (first, middle, last))
field (self, 'birthdate', birthdate)
method (self, 'calculateAge', (self) => dateDiff (newDate, self.birthdate))
method (self, 'sayAge', (self) =>`I am ${self.calculateAge()} years old`)
})
const p2 =
Person ('Gerald', 'Jay', 'Sussman', newDate ('February 8, 1947'))
console.log (p2.sayAge ())
// I am 71 years old
Get creative and invent any other features you want
- Maybe you want to make an
overrideMethod
that gives you the ability to define a new method with the same name, but still give the caller access to both methods - Maybe you want
privateMethod
orclassMethod
helpers - Maybe
field
could be enhanced to emit events when values changed - Maybe
field
could be changed so that values cannot be set, wheremutableField
could be used for fields that can change
Write it how you want it then make your wishes come true. Any limitations are you own.
Post a Comment for "Why Are Higher Order Functions Hiding My Es6 Class Properties?"