0

My code is already working but I want to ask if there's any change to make my function declared as an object instead if no parameters has been provided?

this is my mixin function below:

import Page from "@/models/Page.js";

/**
 * @param  {number} pageId id in page table
 */
export default function (pageId) {
  return {
    data() {
      return {
        page: Page
      }
    },
    created() {
      this.initPageContents();
    },
    methods: {
      async initPageContents() {
        if (pageId) {
          await Page.addPage(pageId);
        }
      }
    }
  }
}

I call it either

  mixins: [
    pageMixin(24),
  ],

or

  mixins: [
    pageMixin(),
  ],

Now with my question again. is it possible to call it as an object that will also behave like the function that doesnt have a parameter?

  mixins: [
    pageMixin,
  ],
Riyenz
  • 2,498
  • 2
  • 9
  • 23
  • See [here](https://stackoverflow.com/a/46063764/4608364) for a possible solution (also possible duplicate?) – Quelklef Apr 29 '19 at 00:50
  • @Quelklef will check on this and will tag it if true – Riyenz Apr 29 '19 at 00:56
  • @Quelklef just an update. It's quite related but I think thats not what im looking for – Riyenz Apr 29 '19 at 02:37
  • You sure? My understanding is that it would let you have an object `pageMixinObj` that acts under almost all circumstances like `pageMixin()`, except that it's callable so `pageMixinObj(...args)` is equal to `pageMixin(...args)`. This seems, to me, to match your situation quite well. – Quelklef Apr 29 '19 at 10:48
  • @Quelklef it should also return an object data same as `pageMixin()` when you call `pageMixin` without the open and close parentheses – Riyenz Apr 30 '19 at 02:42
  • Yes, it would. When I have some free time I will make an answer that explains better what I am thinking. – Quelklef May 01 '19 at 01:41

2 Answers2

0

No, you can't - what you have in that array is a function reference, which means you can only do this:

mixins[0]()

To call your function. If you want the return value of the function to be stored in the array, you'd need to do what you were already doing:

mixins: [
  pageMixin()
]
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
-1

I am not a Javascript expert, but I have cobbled together what I believe is a solution. It is based off of this SO question.

I will reduce your question to the following: "I have a function f. I would like an object o so that o behaves like f(), but o(a, b, c, ...) behaves like f(a, b, c, ...)"

Say, for example, we have a function for creating "people":

function makePerson(firstname, age) {
  firstname = firstname || "Jackson";
  age = age || 17;
  return { firstname: firstname, age: age };
}

and we'd like makePerson to act like makePerson(). I will consider it sufficient to have that makePerson.firstname == "Jackson" and makePerson.age == 17. That is, we care about making all the attributes correct.

We can do this by setting the prototype of makePerson to a new function object which has the attributes that we desire:

// Create a function object
const functionObject = Object.create(Function.prototype);
// Get the default value
const defaultValue = makePerson();
// Copy all the attributes from the default value to the function object
Object.assign(functionObject, defaultValue);
// Make the function object the prototype of our function
Object.setPrototypeOf(makePerson, functionObject);

and see that this works:

console.log(makePerson.firstname); // Jackson
console.log(makePerson.age); // 17

// Still works as a function
console.log(makePerson()); // { name: 'Jackson', age: 17 }
console.log(makePerson("Oliver", 50)); // { name: 'Oliver', age: 50 }

If you want, you could wrap this all up in a function:

function emulateDefault(func) {
  /* Return a function `newFunc` such that `newFunc` behaves like
     `func()` and `newFunc(...args)` behaves like `func(...args)`. */

  // Clone `func`
  const funcClone = Object.create(Function.prototype);
  Object.assign(funcClone, func);

  // Create a function object
  const functionObject = Object.create(Function.prototype);
  // Get the default value
  const defaultValue = func();
  // Copy all the attributes from the default value to the function object
  Object.assign(functionObject, defaultValue);
  // Make the function object the prototype of our function
  Object.setPrototypeOf(funcClone, functionObject);

  return funcClone;
}

and then you could write pageMixin like:

const pageMixin = emulateDefault(function() { ... });

I want to note that I am not 100% positive about everything that is going on here, and there may be edge cases that I have not accounted for. In particular, Javascript cloning is particularly difficult, so emulateDefault may have issues due to that, and I don't know the details of Object.new, Object.setPrototypeOf, or Object.assign.

Quelklef
  • 1,999
  • 2
  • 22
  • 37