28 comments

[ 3.0 ms ] story [ 94.8 ms ] thread
This article has very little content beyond a vague complaint about the keyword 'this' without actually showing of examples of the problem.

It is not as if you have to look far javascript awkwardness - you just have to live with some small but ugly workaround. My guess in this case aliasing "self" to "this" at the top level of deeply nested objects would probably solve the problem.

I second ... er ... this. I read the article and was pretty much 100% confused.
I don't understand what the issue with explicitness is. Python uses self and people seem to be pretty OK with that.
It's really not a big deal. Just a bit cumbersome.

Lua has syntactic sugar where table:method(arg1, arg2, ...) is exactly equivalent to table.method(table, arg1, arg2, ...). All it really does is establish a convention and eliminate "self" from argument listings in methods, but it's still handy - its presence is an immediate sign of OO-style code.

Right, I in fact like using the "this" reference, I use it in Java and C# as well when accessing any member variable.

For me, it helps the way my mind thinks, I instantly know hey, this thing is not local, be careful.

The bigger issue to me is that functions can be passed independent of class in JavaScript, so you have to have some way of making sure the object tags along for the ride.

There are various implementations to do this such as Dojo's dojo.hitch(this, "foo"); which, is not that bad given that you can hand stuff off for callbacks, it is a pretty good trade off. It just takes some getting used to, but the JavaScript is a poorly designed language is a tired meme. I have used it from the day it was released and never saw what all the fuss was about. There are some design decision I would not have made, like no matter where you scope a variable in a routine it is visible to the entirety of that routine. But none of it is so offensive as to earn it the reputation it has had. Further subsequent standards also went a long way to improve on many of the early shortcomings as well.

I'd say this guy is not adapting to the expressiveness of the language. He wants objects, but he's using a prototypical closure oriented language. 'this' is a needed construct to deal with the malleable scope contexts that closures provide.
It does make me question why the books and tutorials I have read on JavaScript want to cover so many object-oriented techniques. Why not treat it more like a functional or "prototypical closure oriented" language? Perhaps the author is on to something.
Because it's so much more ironic to brutalize the language with classicist inheritance and call it 'Prototype.js'
`this` is not a code smell, but trying to do variable hiding/encapsulation of attributes through closures leads to grotty code. Use the leading underscore convention. It's worked in Python for years.

The article author will also be a lot happier when he realizes that Javascript might look like Java but it really wants to be a lisp.

To me, Javascript seems headed in the direction of Self, not Lisp. Not a bad place to end up, by any means, but why do people think Javascript is trying to be Lisp in particular? (I know Eich was influenced by Lisp, but so were ML and Smalltalk.)

Sometimes I wonder if people just mean, "Wow, Javascript is actually a really expressive, dynamic language, once you get past all the idiosyncratic DOM stuff", but don't know enough other non-ALGOL languages to see that expressiveness isn't just a Lisp thing. Because hey, it doesn't have s-expressions, macros/static metaprogramming, an explicit compile-time phase at all, etc. It has much more in common with Lua or Self than Lisp. It could have been a really awesome language if the browser wars hadn't stunted its growth.

> why do people think Javascript is trying to be Lisp in particular?

The reason I said lisp is because Brendan more or less always mentions he wanted to implement a scheme interpreter but Netscape marketing insisted that it look like Java.

As for more closely resembling Self/Lua, I'd largely agree if for nothing other than the obvious object system similarities. On the other hand, I think the idiosyncrasies of javascript like `this` and call/apply, the enforced n-arity of functions, and a lot of the 'convert it to a string' fallbacks (think lisp 1) were attempts at fitting lisp concepts onto the self-like object system. Of course, I have no basis for this so I'm probably wrong, but it makes me feel better when I have to explain them.

I will note that JS is moving into limited metaprogramming with the harmony proxies proposal. I also consider destructuring (another harmony proposal) to be a more functional concept than self/lua, but I actually don't know where that started.

I don't think we should refight the question of encapsulation here. Some people think encapsulation-by-convention is adequate, others don't.

I'm also positing Crockford-style modules.(Since it's pretty clear from the context that I'm following Crockford, you might assume that I know about the Javascript/LISP connection.)

The question remains: is repeated use of "this"

     this.Mill();
     this.Drill();
     this.Fill();
simply semantic vinegar, or does it suggest that the object is not doing its job -- or that we need a new object?
The problem is that you're applying C++ sensibilities to a prototype OO language. `this` doesn't refer to the current class, but to the current object. There are no classes and no methods. Functions don't even really belong to the object they're written in. You can easily rebind (using call/apply) a function to a different object so that it operates as a 'method' of that object. If you have a few minutes, dig up 'Self the video', skip the intro and watch how objects/methods are pulled apart and stuck together. That's the conceptual basis for the object system and it's pretty common for libraries to take advantage of changing `this` to a different object (e.g. `this` is the target element in a jQuery event handler). Opinions are mixed on whether this is ultimately a good idea, but it's part of the language.

Having come from Python to Javascript, I consider this to be explicit and a feature rather than a code smell. I dislike when a language's include constructs dump everything into the local namespace and the `this` is implicit because it means that I can't look at a piece of code in isolation without IDE support and figure out where a particular reference is resolving.

If it really bothers you, coffeescript uses @ in place of this:

    Product::make = () ->
        @mill()
        @drill()
        @fill()
The syntax is definitely awkward. But efforts like coffee-script http://jashkenas.github.com/coffee-script/ are here to alleviate some of these pain points.
Unfortunately, CoffeeScript doesn't support implicit "this". I'm working on that problem, and I hope to share it soon.
The main problem with JS "this" is that in a language where everything else is lexically scoped, "this" is dynamically scoped -- taking the value of whatever object the function happens to be attached to at call time. To use a Ruby metaphor, imagine if "instance_eval" were the default way to call a method.

One of the main features that CoffeeScript adds to help with "this" issue is the bound function literal (the fat arrow). A regular function looks like this:

    add = (num) -> this.value += num
And compiles into the regular JavaScript you'd expect:

    var add;
    add = function(num) {
      return this.value += num;
    };
However, if you define the function with a fat arrow instead:

    add = (num) => this.value += num
You'll get a function bound to the current value of "this", and when you pass the function off to another object as a callback -- a DOM event handler, or success callback from an Ajax request -- the value of "this" doesn't change.

Here's perhaps a better example, from jQuery:

    var self = this;
    $(".row").bind("click", function() {
      this.setText("Clicked!");
    });
And in CoffeeScript, without the "self = this" bit:

    $(".row").bind "click", =>
      this.setText "Clicked!"
Both Python and Lua share this characteristic with Javascript. Is there a name for this language feature, or for languages that share it?

I tend to think of them as "bag-of-things" languages, since they also all share the fact that objects are just tables/dictionaries, and the only thing that distinguishes an attribute reference from a method call is the "()" at the end. Certainly there's a more accepted nomenclature?

> Certainly there's a more accepted nomenclature?

I don't know if there is, but there should be.

The defining aspect seems to be that there aren't pure ADTs, just collections based an associative arrays ("dicts" / "tables"), and methods are just table fields that contain a function. Also, Python has classes where Lua really does just have pure tables with hooks ("metatables", which make it easy to implement prototypes, classes, and many other constructs).

What you're terming "bag-of-things" languages can probably be more aptly described as languages which have both dict/tables/objects and first-class functions.

While there isn't really a term (that I'm aware of) specifically for the this/self convention, both are idiomatic examples of dynamic scoping (compared to lexical scoping); that is, scope is determined at runtime by the most recent stack frame to define a given variable (ie, foo defines "this", then calls "bar", bar sees "this" as it was defined by foo), rather than at lex time.

While there's a correlation between dynamic scoping and explicit "this", it isn't universal: Ruby being the obvious exception.
Recently I have been having a good time developing a large program with this classical inheritance pattern.

  Person = function() {
    this.say = function(phrase) {
      console.log(phrase);
    }; Person.prototype.say = this.say;
  };

  Developer = function() {
    var mypriv = "I have encapsulation";

    this.say = function(phrase) {
      Person.prototype.say.call(this, "Hello");
      console.log("I develop "+phrase);
      console.log(mypriv);
    };
  }; Developer.prototype = new Person();

  var devel = new Developer();
  devel.say("a lot");
Coming from a C++ and Java background, I have put this pattern together from various sources: Crockford, John Resig and others. It has worked great and I dont see any problems with structuring your large JS program in this way.
i simply avoid writing "new" in javascript. ever. well, unless its for Date.

if i really need OO, i use YUI and forget about most javascript caveats. Everything is just too 'wrong' to keep track in your mind.

Everything felt wrong when I started programming in JS for real about a year ago, but now I would say I understand most aspects of it, and can keep track. Im still not ready to let go of classes and classical inheritance though. Not sure if I ever want to.
Take a look at Io. It does prototypes properly. And they are, in fact, pretty nice to work with. I wouldn't mind getting rid of classes in my day-to-day life.
Please, please don't spread this "object factory" pattern any further than it's already gone. It's an incredibly inefficient way to do OOP in JavaScript.

Every time you create a new instance of a Developer, you redefine every single function. This makes instantiation far slower than it would be if you used prototypes, and leaks memory like crazy: N Developers means N copies of each function.

So, first, it's slow -- take this test: https://gist.github.com/459112

Webkit: http://tinyurl.com/2csgzez Firefox: http://tinyurl.com/29wd2ms

And second, the memory use. Take a moderately-sized class, with ten member functions. The last time I benchmarked it in Chrome, using real prototypes, it takes a little under 32 megabytes of RAM to create a million instances of it. Try to create a million instances using the pattern you have above, and it spins the browser for minutes, and eats up 368 megabytes of RAM. IE just crashes.

If you're doing OOP in JS -- please use prototypes as Eich intended...

Thanks for the benchmarks, I know the tradeoff for using this pattern.

Im aware of that the function is defined in each object, and that it takes up memory. I dont agree that the memory is leaked, it is reclaimed when the object is deleted.

As I never create millions of instances of objects, and this patterns dont seem to have a measurable impact on the rendering loop in my project, Ill just continue using it for now.

I would call the pattern you propose to be the "object factory" pattern. And I am curious how to do classical inheritance and encapsulated vars with it.