Constructor For Callable Object In JavaScript
Solution 1:
Turns out it's actually possible. When the function is created, either by using function
syntax, or Function
constructor, it gets internal [[Call]]
property. It isn't a property of function itself, but rather property that any function gets when constructed.
While that only means that anything with [[Call]]
could be only Function
when it's constructed (well, there is one exception – Function.prototype
itself that doesn't inherit from Function
), that doesn't mean it cannot become something else later, while preserving [[Call]]
property. Well, provided your browser isn't IE < 11.
The thing that allows changing the magic would be __proto__
from ES6, already implemented in many browsers. __proto__
is a magical property that contains current prototype. By changing it, I can make function that inherits from something that isn't Function
.
function CallablePoint(x, y) {
function point() {
// Complex calculations at this point
return point
}
point.__proto__ = CallablePoint.prototype
point.x = x
point.y = y
return point
}
// CallablePoint should inherit from Function, just so you could use
// various function methods. This is not a requirement, but it's
// useful.
CallablePoint.prototype = Object.create(Function.prototype)
First, the constructor for CallablePoint
makes a Function
(only Function
s are allowed to begin with [[Call]]
property. Next, I change its prototype, so it would inherit CallablePoint
. At this point I have a function that doesn't inherit from Function
(sort of confusing).
After I defined constructor for CallablePoint
s, I set the prototype of CallablePoint
to Function
, so I have CallablePoint
that inherits from Function
.
This way, the CallablePoint
instances have prototype chain: CallablePoint -> Function -> Object
, while still being callable. Also, because the object is callable, it has according to the specification, typeof
equal to 'function'
.
Solution 2:
I'm not sure if you're aware that your object will only be an instance of CallablePoint
if you use the new
keyword. By naming it "callable", you make me think you don't want to use new
. Anyway, there is a way to force an instance to be returned (thanks for the tip, Resig):
function CallablePoint(x, y) {
if (this instanceof CallablePoint) {
// Your "constructor" code goes here.
// And don't return from here.
} else {
return new CallablePoint(x, y);
}
}
This will return an instance of CallablePoint
regardless of how it was called:
var obj1 = CallablePoint(1,2);
console.log(obj1 instanceof CallablePoint); // true
var obj2 = new CallablePoint(1,2);
console.log(obj2 instanceof CallablePoint); // true
Solution 3:
If you want the CallablePoint()
constructor to return an object of type CallablePoint, then you can do something like this where the CallablePoint object contains a point as a property of the object, but remains a CallablePoint object:
function CallablePoint(x, y) {
this.point = {};
this.point.x = x
this.point.y = y
}
or, if what you're really trying to do is to make a function that returns you an object of CallablePoint, then you can create a factor function:
function CallablePoint(x, y) {
this.point = {};
this.point.x = x
this.point.y = y
}
function makeCallablePoint(x, y) {
return new CallablePoint(x,y);
}
Post a Comment for "Constructor For Callable Object In JavaScript"