Something my language does differently from most object-oriented languages is that there’s no implicit this value for member functions. This may seem strange at first, but it solves a few problems.
The next level of this problem is that when you have nested object declarations, this only allows you to access the innermost object’s members. That sounds a little contrived, but it’s a real problem. For example, if you have an object for your module’s public members, and within it you have another object literal, that nested object’s member definitions cannot access the module’s public members.
The way I solved this in my language is to replace the caller-provided this with capturing the object’s members as part of a lexical closure. Object members may be accessed within the scope of the object definition, and it will resolve to the inner-most object that defines the name. Internally, there isn’t a single this, and member names need to be resolved against a stack of objects that were in the lexical scope.
To make things a little bit clearer for everybody (humans and machines), member names must start with a . symbol, both when declared and when accessed. Objects may also include definitions that don’t have a . prefix, but they are the equivalent of private members: they cannot be accessed outside the object definition. When an object is used as a prototype, its public and private members are copied into the derived object, and are bound to the new object where they previously accessed the prototype’s public members.
There are still some remaining problems:
- There aren’t aliases for the objects that are being used to resolve member names. This is rarely needed, but it is occasionally useful. The simplest solution would be to define this(or .) to be the innermost object context, but that doesn’t allow e.g. memberFunction to access the module object it is being used from; it can’t simply refer to myModule, as myModule may be used as a prototype for another object, and if that is how memberFunction was accessed, then that prototyped object is what you want.
- I’m torn on using a symbolic <- for object prototyping. Its meaning is similar to class inheritance, where the left operand is a prototype object for the right operand. An operator is more flexible than making the prototype part of the object literal syntax, and <- makes the non-commutative nature of the operator clear, but the meaning isn’t as obvious to people who don’t know the language as using a keyword like extends would be. But what’s an appropriate keyword that keeps the prototype as the left operand?