Must built-in prototypes also be valid instances? (Was: Why DataView.prototype object's [[Class]] is "Object"?)

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Oct 2 11:25:53 PDT 2012


On Oct 2, 2012, at 10:52 AM, Herby Vojčík wrote:

> 
> 
> Allen Wirfs-Brock wrote:
>> 
>> If you really need to strongly tie instantiation with branding you
>> probably have to use a factory function:
>> 
>> module Fooishness {
>>    export function FooFactory ( ){return  new Foo};
>>    FooFactory.isFoo = function (obj) {return !!obj. at FooBrand};
>> 
>>    private @FooBrand;
>>    class Foo {
>>       constructor() {
>>            /* establish the internal Fooness of the instance */
>>            this. at FooBrand = true;
>>       }
>>    }
>> }
> 
> var iWillBeFoo = {};
> Fooishness.FooFactory().constructor(iWillBeFoo);
> 
> In fact, it has its logic to `newFoo. at FooBrand = true;` in factory, which solves it, hopefully cleanly enough.
> 
>> Allen
> 
> Herby
> 

Good catch, I forgot that the constructor is still exposed as a property on the instance.   The other way to prevent the constructor from being used to brand a pre-existing object is force an instantiation inside the constructor:

private @FooBrand;
class Foo {
  constructor() {
       let newFoo = Object.create(Foo.prototype);
       /* establish the internal Fooness of the instance */
       newFoo. at FooBrand = true;
       return newFoo;
  }
}
Foo.isFoo = function (obj) {return Reflect.hasOwn(obj, at FooBrand) && !!obj. at FooBrand};

But this prevents Foo branding of subclasses of Foo.  There is a tension here that I don't think is necessarily resolvable. To me, it is another example why such class branding should only be used in specific high integrity situations and not as a general practice for all classes.

Allen


More information about the es-discuss mailing list