Having isFoo succeed on an instance of Bar is correct. But there's another case that's more worrisome:
Foo foo = new Foo(); Baz baz = Object.create(foo); By Allen's pattern, isFoo will also succeed on an instance of baz. OTOH, were the branding done with a WeakMap or the brandcheck done with an own check.... On Tue, Oct 2, 2012 at 10:12 AM, Allen Wirfs-Brock <al...@wirfs-brock.com>wrote: > > 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 > > > > > -- Cheers, --MarkM
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss