Although I am not an expert in Javascript, I have managed to piece together what I think is a viable solution. My approach is influenced by this particular question on SO.
To simplify your query: "I possess a function f
. I desire an object o
that mimics the behavior of f()
, where o(a, b, c, ...)
mirrors f(a, b, c, ...)
"
Imagine we have a function for generating "people":
function makePerson(firstname, age) {
firstname = firstname || "Jackson";
age = age || 17;
return { firstname: firstname, age: age };
}
We wish for makePerson
to behave like makePerson()
. Specifically, it should uphold conditions such as
makePerson.firstname == "Jackson"
and
makePerson.age == 17
. Essentially, ensuring all attributes are accurate.
To achieve this, we can set the prototype of makePerson
to a new function object with the desired attributes:
// Create a function object
const functionObject = Object.create(Function.prototype);
// Obtain default value
const defaultValue = makePerson();
// Copy all attributes from default value to function object
Object.assign(functionObject, defaultValue);
// Set function object as the prototype of our function
Object.setPrototypeOf(makePerson, functionObject);
If we test this out:
console.log(makePerson.firstname); // Jackson
console.log(makePerson.age); // 17
// Still functions correctly
console.log(makePerson()); // { name: 'Jackson', age: 17 }
console.log(makePerson("Oliver", 50)); // { name: 'Oliver', age: 50 }
You could encapsulate everything within a function if preferred:
function emulateDefault(func) {
/* Return a function `newFunc` that behaves like
`func()` and `newFunc(...args)` simulates `func(...args)`. */
// Duplicate `func`
const funcClone = Object.create(Function.prototype);
Object.assign(funcClone, func);
// Create a function object
const functionObject = Object.create(Function.prototype);
// Get default value
const defaultValue = func();
// Copy all attributes from default value to function object
Object.assign(functionObject, defaultValue);
// Set function object as the prototype of our function
Object.setPrototypeOf(funcClone, functionObject);
return funcClone;
}
This way, you can define pageMixin
like so:
const pageMixin = emulateDefault(function() { ... });
Note that I cannot guarantee everything is foolproof here, and there may be unresolved issues with edge cases. Particularly, Javascript cloning can be tricky, hence emulateDefault
might face challenges due to that. Additionally, details about Object.new
, Object.setPrototypeOf
, or Object.assign
are not entirely clear to me.