using Private name objects for declarative property definition.

Brendan Eich brendan at
Sat Jul 9 13:43:43 PDT 2011

On Jul 9, 2011, at 11:19 AM, Allen Wirfs-Brock wrote:

> A consideration here is that whatever conventions we follow sets a precedent for user written code. I don't think we want to encourage the addition of such classification functions to Object or Object.prototype.  So from that perspective Array.isArray, Function.isGenerator, and Proxy.isProxy are better exemplars than Object.isArray, etc.

Do we want users extending Array or Function? Same problem as applies to object. In Edition N+1 we then collide. I don't see a difference in kind here.

> Another consider is whether such classification schemes should use methods or data properties. An instance side, isFoo() method to be useful generally will also require the addition of an isFoo() method to Object.prototype while a instance side-data property can be tested without augmenting Object.prototype (({}.isFoo) is a falsey value).  Also most user code classification schemes will require some sort of instance-side tagging or testing to actually determine whether the instance is in the category. 
> For those reasons, I think the best classification scheme is usually via an instance-side public data property with a truthy value. 

I don't agree, because detecting truthy valued properties from host objects (proxies) can have effects. Calling a well-known predicate function that has no side effects is better.

> But there are some exceptions.  For the legacy built-ins such as Array is less risky from compatibility perspective to add properties to the constructor than to the prototype. However, for new built-in this isn't an issue. Another consider is meta layering: meta-layer functions shouldn't be exposed on application layer objects. Proxy.isProxy is a good example.  Proxy instances operate as application objects in the application layer.  The public face of application objects shouldn't be polluted with a meta-layer method such as isProxy.

Do we want intercession by proxies for any of these isFoo predicates?

>> Why not Function.isGenerator? Because the prototype method is more usable when you have a function in hand and you want to know whether it's a generator. If you have any value x, you'll need (typeof x === 'object' && 'isGenerator' in x) guarding the x.isGenerator() call, but we judged that as the less common use-case.
> Why not just make it a boolean-valued data property?

See above, and also isArray and other isFoo predicates (isNaN) realized via functions, not data properties.

>> Could be we were wrong, or that being consistent even in the hobgoblin/foolish sense is better. But Object.isGenerator crowds poor Object more.
>> Notice how there's no need for Function.isFunction or Object.isFunction, due to typeof (function(){}) === 'function'. That's another dawn-of-time distinction that does not fit the primitiive types vs. object classification use-case I mentioned in the last message -- testing whether x is callable via typeof x === 'function', at least for native if not host objects, is the use-case here.
> But this is a special case that does not extrapolate to other situations.

Agreed, although we've said we'll consider typeof-result extensions in the future, e.g., for user-defined value types.

>> Some of these questions are at this point more about aesthetics and Principles than about usability. And we have historic messiness in how things have grown.
> In a utilitarian language like JS, usability and aesthetic considerations should be closely linked and consistency is a significant usability factor. .  Principles are a way to get consistent application of such  aesthetics . 

It's hard to disagree, but that doesn't settle disagreements, e.g., on data properties that are true-valued or missing, so undefined-falsy, vs. pure predicate functions.

In the worst case, our argument now must go meta. I don't want to do that. My argument for pure predicates is concrete, not abstract.


More information about the es-discuss mailing list