
Javascript: is 'this' a code smell? - blasdel
http://www.markbernstein.org/Nov10/Javascriptisuthisuacodesme.html
======
cosbynator
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.

~~~
CoffeeDregs
I second ... er ... this. I read the article and was pretty much 100%
confused.

------
grayrest
`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.

~~~
silentbicycle
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.

~~~
grayrest
> 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.

------
Detrus
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.

~~~
jashkenas
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!"

------
shubber
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?

~~~
cheald
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.

~~~
shubber
While there's a correlation between dynamic scoping and explicit "this", it
isn't universal: Ruby being the obvious exception.

------
ghotli
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.

~~~
dmatking
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.

~~~
blasdel
Because it's so much more ironic to brutalize the language with classicist
inheritance and call it 'Prototype.js'

------
bni
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.

~~~
jashkenas
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...

~~~
bni
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.

------
silentbicycle
Dijkstra would not have liked 'this'.

------
makuro
[http://www.amazon.com/JavaScript-Patterns-Stoyan-
Stefanov/dp...](http://www.amazon.com/JavaScript-Patterns-Stoyan-
Stefanov/dp/0596806752)

Boom. Get it while it's hot.

------
axiak
I don't understand what the issue with explicitness is. Python uses self and
people seem to be pretty OK with that.

~~~
silentbicycle
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.

~~~
kls
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.

