3

I am creating a library with a function that might be called many thousands of times every second. This function requires the new constructor so as to bind a new set of data to a fixed prototype like so:

var internalFunc = function(a) {
   this.foo = a;
};
internalFunc.prototype = {
   something: 'some value',
   anotherIndex: 'another value',
   /* ... */
};

So, the way I am currently getting internalFunc to be called with a new constructor is by using a second function sort of like what one could call a 'constructor proxy'.

var funcThatGetsUsed = function( someArgument ){
     return new internalFunc( someArgument );
};

However, getting back to the main issue, this funcThatGetsUsed can get called many thousands of times a second. So, it might reduce the size of the library, and it could increase the speed of the code if I was able to eliminate that middle man 'constructor proxy' function, and just bind the new constructor to the internalFunc, maybe in a similar fashion to the bind function like so:

var funcThatGetsUsed = internalFunc.bindToConstructor('new');

So, is there a way to 'bindToConstructor' in javascript to reduce the function call overhead?

Please note that the reason for why I can't just tell the user of the library to use the new operator is because that would kind of defeat the purpose of this particular library. Case and point: JQuery uses a 'constructor proxy' function. Just type in something like console.log($.toString()), and you should see something like this:

> console.log("'" + $.tostring() + "'")

'function (a,b){return new n.fn.init(a,b)}'

Please note that I am targeting Edge and above, so the solution doesn't have to work in Internet Explorer. What I mean by 'targeting Edge' is that if it works in Edge, then it will, of course, work in every other browser.

Jack G
  • 4,553
  • 2
  • 41
  • 50
  • 1
    Btw, instead of worrying about the extra function call, you should worry about instantiating thousands of objects every second. – Bergi May 23 '17 at 23:31
  • 3
    There was [an idea in an operator proposal](https://github.com/tc39/proposal-bind-operator/issues/25) for `internalFunc::new` that would do what you are looking for. But No. – Bergi May 23 '17 at 23:34
  • @Bergi please read the **entire** question. Thats what im currently doing, but I am just curious if there's a more efficient way. Also, this is for a library i'm writing. My goal as the writer of the library is to make the library as efficient as possible for people who misuse it by calling it thousands of times a second. –  May 23 '17 at 23:40
  • To which my exact answer was "*No, there's not*" (except for putting the `new` right at the call location). – Bergi May 23 '17 at 23:41

1 Answers1

1

You can use Reflect.construct()

var funcThatGetsUsed = Reflect.contruct(internalFunc /* , [args] */ )
guest271314
  • 1
  • 15
  • 104
  • 177
  • 2
    That doesn't bind anything, it just replaces the `new` operator (and requires arguments to be passed as an array) – Bergi May 23 '17 at 23:35
  • 1
    This was exactly what I was looking for! Thank you so much! I'll mark your answer accepted as soon as SO lets me! –  May 23 '17 at 23:35
  • 1
    @Bergi I wasn't asking for something that binds. I was asking for something that is comparable in functionality to something that binds which is what this is. –  May 23 '17 at 23:36
  • 1
    `Reflect.construct` does not avoid either using a "constructor proxy" function or have the caller use extra syntax, which was what the question asked for. – Bergi May 23 '17 at 23:39
  • @3.1415926535897932384626433833 No, it's not comparable in functionality. `Reflect.construct` does not help to create your `funcThatGetsUsed`. – Bergi May 23 '17 at 23:41
  • 3
    @Bergi The Question has several layers. One portion of inquiry is how to not use `new` operator though achieve same result. You can probably select one or more of the layers within OP to place through your mortar and pestle. – guest271314 May 23 '17 at 23:42
  • 1
    @guest271314 I don't see any other layer than "*is there a way to 'bindToConstructor' in javascript to reduce the function call overhead?*". `Reflect.construct` might avoid the new operator, but it does not reduce call overhead. – Bergi May 23 '17 at 23:43
  • 2
    @Bergi _"Please note that the reason for why I can't just tell the user of the library to use the new operator is because that would kind of defeat the purpose of this particular library."_ – guest271314 May 23 '17 at 23:44
  • @guest271314 So you think "*Tell the user to use `Reflect.construct*" is a sensible solution? – Bergi May 23 '17 at 23:45
  • 1
    @Berengi because it uses an internal proxy, there is a much greater possibility of efficiency. That's what this question is about. – Jack G May 23 '17 at 23:45
  • @lolzerywowzery What's an "internal proxy"? And no, engines optimise the `new` operator, nothing else. – Bergi May 23 '17 at 23:46
  • 2
    Emphasize 'possibility'. Current engines may only optimize for the `new` operator, but future engines have the potential to better optimize for `Reflect.contruct` than a 'constructor proxy' function. – Jack G May 23 '17 at 23:48
  • 1
    FINALLY! SO finally let me mark this correct answer as correct. –  May 23 '17 at 23:49
  • 1
    @lolzerywowzery You still need the construct proxy function around the call to `Reflect.construct`, so that doesn't matter in terms of optimisability. The code in the current answer doesn't work, `funcThatGetsUsed()` would throw an exception. – Bergi May 23 '17 at 23:52
  • 1
    @Bergi Cannot evaluate what is "sensible" for another two-legged. Can only provide possible options that could be tried. It is up to OP to decide what is appropriate for their application. Else, what is the purpose of more than only one Answer, your Answer, or another "sensible" users' one Answer, at any Question at SO? One purpose would be that you can post your own Answer, decrying this Answer as "insensible" or "nonsensical" and proposing a "sensible" solution - if you determine there is an issue at OP at all. – guest271314 May 23 '17 at 23:53
  • 1
    Guys Reflect.construct() Is completely equal to call new computational speaking. I totally agree with @Bergi. Than if the point is that you dont like the new keyword and the question is how to replace that, ok that does the job. Here MDN: "The static Reflect.construct() method acts like the new operator as a function. It is equivalent to calling new target(...args)." – quirimmo May 23 '17 at 23:54
  • 1
    P.s. and what has been posted about jQuery which wraps the new inside a factory method (that I think is a more appropriate term than proxy constructor) is another proof in my opinion of that – quirimmo May 23 '17 at 23:58
  • 1
    @guest271314 Gathered that some users have issues with sensibility. Regardless of what the OP decides to accept because believing it to work, this user can judge whether solution is appropriate for requirements at question. – Bergi May 24 '17 at 00:22
  • @lolzerywowzery I checked out your answer and using bind means just a way to dynamically pass a function. So it is just syntactic sugar. You are always calling that function then. Yes, it is elegant to write, but actually what is called is always the same method. I think that this question makes sense if someone says: "I dont want to use new because I don't like the new word". But giving as motivation the number of calls and performances, then it doesn't make sense to just call a static method which actually it is equivalent to call new computational speaking. – quirimmo May 24 '17 at 00:25