typeof null

Allen Wirfs-Brock allen at wirfs-brock.com
Thu May 10 08:22:39 PDT 2012


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

> 
> 
> Allen Wirfs-Brock wrote:
>> ...
>> 
>> Whenever anybody says they need to do a type test (or instanceof
>> test) we need to ask them: Why? What is it you really need to know.
>> Smalltalkers learned fairly early that type/class testing was an
>> anti-pattern. It makes code brittle and difficult to fix or extend.
> 
> Yes, smalltalkers frown upon isKindOf: which is like JS instanceof. But they have their isNumber, isInteger, isNil, isWhateverElse methods. At least for "built-ins" they can be pretty sure than sending isInteger returns true for any object that pretends to be integer, even in case it would be a proxy from different Smalltalk (I am trying to make a case analogous to cross-frame). So for these "built-in" types, checking that works cross-frame should probably be there (akin to Array.isArray).

Or they use an explicit class check:  anObj class == Array
which is also frowned upon. 

So, yes, situations where behavioral classification needs to be done in Smalltalk is preferably done with isFoo methods.  They are better than class (including isKindOf:) tests because they decouple behavioral classification from the implementation class hierarchy.  However, the downside of such methods (in Smalltalk) is that they generally require monkey patching the negative case into class Object.  EG, add to class Object's instance behavior the method:
    isFoo
        "Only classes that explicitly over-ride this to return true are considered to be fooish"
        ^false

This has similar maintenance issues to what people see in JS when they start augmenting the built-in prototypes with new properties.

For this use case that problem is avoidable in JS.  Since accessing a missing property property returns a falsey value the negative case doesn't have to be monkey patched into into Object.prototype.

var obj1 = {
    isFoo: true;
    doFooishThings: function() {...}
};
var obj2 = { };
 if (obj1.isFoo) obj1.doFooishThings();  //call the method
 if (obj2.isFoo) obj1.doFooishThings();  //does not try to call the method

Note that in this and many other similar situations the isFoo method is actually redundant.  You would get the same effect by saying:

 if (obj1.doFooishThings) obj1.doFooishThings(); 

this suggests that a useful operator might be a conditional property access, perhaps something like:

??obj.doFooishThings();

which parses as
CallExpression :
    ?? MemberExpression Arguments

If conditionally calls the value of the MemberExpression if it is not undefined.

Allen




More information about the es-discuss mailing list