Please some small improvements

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Mar 20 16:34:34 PDT 2012


On Mar 20, 2012, at 3:57 PM, John J Barton wrote:

> On Tue, Mar 20, 2012 at 2:53 PM, Allen Wirfs-Brock
> <allen at wirfs-brock.com> wrote:
>> 
>> On Mar 20, 2012, at 2:10 PM, John J Barton wrote:
>> 
...
>> 
>> In ES.next, based upon current proposals, the equivalent can be directly
>> expressed  using <| without any additional function calls:
>> 
>>  LoadCodeUnit.prototype = CodeUnit.prototype <| {
>>    allowLoad: true,
>> 
>>    get moduleSymbol() {
>>      return this.project.getModuleForUrl(this.url)
>>    },
>> 
>>    ...
>> 
>> In other words, <| is the operator forms of the function you are requesting
>> for the object literal use case.
> 
> I agree that the <| would be a good match to the use shown in the Traceur code.
> 
> However, the example shows a significant pitfall waiting for the
> unsuspecting: data properties on the prototype. The allowLoad
> properties does appear to be intended as a 'static' or class value. In
> projects that never use object literals for data properties, then this
> ok. But many devs will use object literals for both functions and
> data. Soon or later we get burnt.

Whether such a data property is good or bad, really depends upon the context.  Maybe allowLoad:true is simply a default that is over-ridable on a per instance basis.  In that case, what is wrong with putting it on the prototype?  Would you be happier if it was defined as:
  get allowLoad() {return true}
?

If that is the same it makes it harder to over-ride for individual instances because they need to do a Object.defineProperty to install the over-ride rather than a simple assignment.

> 
> I suppose the <| operator has the advantage that linters can probably
> report data properties in the RHS at edit time.  Making this a compile
> error should be considered.

But there are plenty of other uses of <| in conjunction with object literal data properties.

For example, you can use <| as an alternative to the new operator.  Assume that you have the definition I quoted from Tracer then to create a LoadCodeUnit instance you might say:

    let aCU = Load.CodeUnit <| {allowLoad: false, loader: myLoader, url: "foo.js", state: NOT_STARTED};

to create one that doesn't allow loading. 


As another example, you can use prototype inheritance to buildup data records with shared parts.  For example:

let wb = {lastName: "Wirfs-Brock"};
let wbOR = wb <| {state: "Oregon"};
let allenwb = wbOR <| {firstName: "Allen"};
let rjw = wbOR <| {firstName: "Rebecca"};

If you play nanny based upon only one usage pattern you preclude other uses.  It's probably better to make such rules part of a project specific linter.

Allen




More information about the es-discuss mailing list