Strict undefined this

Mark S. Miller erights at google.com
Sat Aug 30 15:10:51 PDT 2008


On Sat, Aug 30, 2008 at 2:02 PM, Erik Arvidsson
<erik.arvidsson at gmail.com> wrote:
> On Fri, Aug 29, 2008 at 22:51, Brendan Eich <brendan at mozilla.org> wrote:
>> #c wins by maximizing TC purity, utility, and safety.
>>
>> /be
>
> d) Lexical scoping
>
> I thought one of the points with changing *this* in strict mode was to
> make it use lexical scoping where it "makes sense"?

I agree with all the goals you state. There was an earlier proposal,
made by Crock and agreed to before March by the overall committee
(both the 3.1 and 4 factions). It was even somewhat orthogonal to
strict-mode, and would have made the non-strict language more
intuitive as well. However, at the March meeting I presented something
like the following example which demonstrates a fatal ambiguity:

    function PointMaker() {
      this.count = 0;
      that = this;

      function Point(x, y) {
        this.x = x;
        this.y = y;
        that.count++;
      }
      Point.prototype.getX = function() { return this.x; }
      Point.prototype.setX = function(x) { this.x = x; }

      this.Point = Point;
    }

// Each PointMaker is a factory for new points that counts how many
points it made:
var pointMaker = new PointMaker();

foo(new (pointMaker.Point)(3,5));

// How many has it made so far?
print(pointMaker.count); // 1

If foo() only uses the point it's been given in the expected ways, all
is cool. But what if foo() says:

function foo(pt) {
  var setX = pt.setX;
  setX(44);
}

or equivalently

function foo(pt) {
  (true && pt.setX)(44);
}

Under Crock's proposed rule, this will bring about the effect of

    pointMaker.x = 44;

even though one would have thought foo() had no access path whatsoever
to pointMaker. In other words, a lexical-this-defaulting rule as Crock
proposed, and as I gather you seem to be proposing, would cause the
'this' in setX to be bound to the lexically enclosing 'this' when setX
is called as a function. This violates it's authors intent in the same
way that the non-strict global-this-capture does. The only difference
is that inappropriate access is being provided to pointMaker rather
than the global object.

If a lexical this-capture rule can be made to work without these kinds
of problems, it would indeed be better than having to explain
".bind(this)" to ES programmers. Suggestions?

-- 
    Cheers,
    --MarkM


More information about the Es-discuss mailing list