Closed jrf0110 closed 9 years ago
Yeah this would be nice. Perhaps something like stampit.is(stamp, obj)
then the original stamp becomes the "type"?
right.
Maybe even with some extra sugar:
var factoryA = stampit({ ... });
var a = factoryA();
a.is( factoryA );
factoryA.didStamp( a )
JS does not allow this sort of object metadata. Even using raw JS objects, instanceof
isn't really type data. Instead, it simply checks the object's prototype identity against Constructor.prototype
, which is very brittle.
The factory could keep an identity history of every stamp created, but that would create memory overhead that may not be appropriate for every use of Stampit (particularly games or event systems cranking out lots of objects).
The instances can't keep metadata without tacking properties onto the stamp that may interfere with the author's intentions.
Barring those options, here is what we could implement:
Since that's not actually a strong guarantee, is it worth putting it in Stampit core?
If you actually need this kind of thing, here are options you could do in user space:
stampit.compose(a, b, c).state({hasBehaviors: [a, b, c]});
When you start getting into the need to identify the type of instance you're looking at rather than simply ducktyping, it may be a code smell that should push you in the direction of functional, reactive, or dataflow programming. See The Two Pillars of JavaScript Pt 2.
Looks like probably your best bet is using this if you must: https://www.npmjs.com/package/is
-1 for putting it in stampit core
instanceOf
or obj.is(Stamp)
method@jrf0110 I had a similar proposal. See #44. I know your pain. :)
Although, I'd agree with @ericelliott that this only makes things worse when we try to mimic classical inheritance. See this funny tweet.
If you really need your object to be recognizable then the best way would be to use ES6 Symbols. Stampit does not support it (yet?).
The other way around would be to create one more function in either your stamp
myStamp.hasCreated = function (obj) { /* ducktype it yourself */ };
or add a method to your objects' prototype:
var myStamp = myStamp.methods({
createdBy: function (stamp) { return stamp === myStamp; }
});
However, in last 18 months I haven't found myself needing anything of the above. Ducktyping was always more than enough.
I believe that we should move rarely needed functions out of stampit main file, but put them to a subfolder. For example stampit.isStamp
and the proposed stampit.is()
. And use them like so:
var isStamp = require('stampit/is-stamp');
or
require('stampit/has-created')(stampit);
myStamp.hasCreated(someObj);
Changing stampit core
:+1:
One and a half years later... What is the conclusion here? I'm not seeing how to tell if something is an instance of a particular stamp. Kindly point me to the right doc? : )
@sheriffderek There will never be a standard way to identify an object origin. First of all, we think that's a bad thing. Second, you can implement that yourself as a 3 lines composable behaviour (aka stamp). See here for inspiration - https://github.com/stampit-org/stampit/blob/master/docs/advanced_examples.md#attach-function-to-prototype-memory-efficient
Given an object instance, it'd be useful to know if it has certain behaviors:
This would require some explicit meta data about the stamp, but none-the-less, is useful.
I see JS's non-linear inheritance as being pretty similar to the Components pattern in OO. The problem is that there's nothing to say what a thing is with any guarantee because types suck in JS.
In C#/Unity, if you wanted to see if an object had certain behaviors, you would do something like this:
Having used stampit for a little while, here's what I'd like to see:
instance.prototype.constructor
, but better