On Oct 1, 2012, at 10:37 PM, Brendan Eich wrote:
> Brendan Eich wrote:
>> But if we have a solid branding mechanism (like Domado's ideal in latest
>> browsers? ;-) then that should be used universally and this becomes a
>> don't-care.
>
> Just to be crystal clear:
>
> * in pre-ES6 browsers, no @@toStringTag in the language to hack around with.
>
> * in ES6+ browsers, the better branding mechanism and @toStringTag (one @) as
> public symbol, no worries.
>
> Yes, this makes a fork in JS code that wants to do tag testing. Old code must
> use O_p_toString_call (original value of, safe call binding) and string
> compare. New code wants the better and universal scheme.
>
> /be
>
Yes, exactly what I envision. New code that needs to do branding should do it
in a new way. But I still think we need to protect the integrity of the old
mechanism in the presence of @@toStringTag.
It is also probably worthwhile taking a look at how internal branding is done
in the draft spec. for Map.
We also need to be careful about making a branding mechanism too prominent. If
we do, too many people will misuse it as a poor man's nominal type system when
they really should be doing behavior typing (or even more likely no explicit
type checking at all). Past experience is that excessive class brand checking
is an anti-pattern for dynamic OO languages.
I think we have all the language features need to do reliable branding by ES
programmers where they need it. We just need to establish the patterns for
doing that. Here is the one I propose:
private @FooBrand;
class Foo {
constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
}
}
Foo.isFoo = function (obj) {return !!obj.@FooBrand};
private @BarBrand;
class Bar extends Foo {
constructor() {
super();
/* establish the internal Barness of the instance */
this.@BarBrand = true;
}
}
Bar.isBar = function (obj) {return !!obj.@BarBrand};
Note that an instance of Bar will be true for both Foo.isFoo and Bar.isBar
This pattern is fine as long as it is ok that anything processed by the Foo or
Bar constructor gets branded because not, anybody can do:
let myFoo = Foo.call({ });
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.@FooBrand};
private @FooBrand;
class Foo {
constructor() {
/* establish the internal Fooness of the instance */
this.@FooBrand = true;
}
}
}
Allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss