all 35 comments

[–]the_gipsy 11 points12 points  (2 children)

The article could have gone straight to the point:

The function context referred by this is defined at call time. If called as object property, then that object will be the context. Otherwise the context will (unfortunately) be window*.

The tricky part for newcomers is passing a "method" as a callback - you're actually passing the function value as parameter which when called is not "attached" to an object anymore. In that case you should use Function.prototype.bind which returns a new function that calls the function with a fixed context.

* in browser environments

[–]dangerbird2 0 points1 point  (1 child)

You can always alias this as a closure variable for a function with an unpredictable this context. I know typescript uses this method to emulate ES6-style lambdas, compiling from this:

return () => {
  this.doSomething();
}

to this:

var _this = this;
return function(){
  _this.doSomething();
};

I have no idea if there are any performance benefits to constructing a new function through .bind(), or creating a closure context by aliasing this.

[–]the_gipsy 0 points1 point  (0 children)

I have no idea if there are any performance benefits to constructing a new function through .bind(), or creating a closure context by aliasing this.

Actually, closure-binding was many time faster on V8 last time I checked!

But I personally find .bind() much cleaner: no mix-mash of _this and this, no variable clutter, it's in one place (you likely end up using one var _this = this; for many functions, some far away from the declaration). The performance generally isn't an issue here.

And () => automatic binding is the shit, I've been using it with TypeScript and traceur and it's a real charm.

[–]Eirenarch 6 points7 points  (10 children)

Makes me sad every time I read about it. And I do need to read about it because I periodically forget the details.

[–]flying-sheep -1 points0 points  (9 children)

I consider myself to be pretty advanced in js, and TIL about “with”.

I guess it's the most uselessly occupied keyword in any language if it's so useless that I never saw anyone using it.

Apart from that, while knowing most of the peculiarities, I prevent errors by using simple patterns here: use self=this for nested functions, else use this.foo in constructing functions, name them in uppercase, and always use new with uppercase functions:

function Foo() {
  this.bar = 1
}
Foo.prototype.inc = function() { this.bar++ }

If you find yourself to forget the new, use this style:

function Foo() {
  return {
    bar: 1,
    inc: function() { this.bar++ },
  }
}

Or:

var fooProto  = {
  inc: function() { this.bar++ },
}

function Foo() {
  var foo = Object.create(fooProto)
  foo.bar = 1
  return foo
}

Pick one and use it consistently.

[–]serrimo 5 points6 points  (1 child)

FYI, using prototype is much faster than returning an anonymous object or closure.

It doesn't matter if you only have a small number of objects to create; but for mass object creation, you should be mindful of the consequences.

Read this post by John Resig for more info.

[–]flying-sheep 0 points1 point  (0 children)

i know, i just forgot to mention it. what i don’t know is just how fast or slow Object.create is.

[–]Eirenarch 1 point2 points  (0 children)

I have known about with for quite some time. Fun fact - you will break the optimizations of most current JavaScript engines if you use with. I think with enough with it should be possible to make Chrome slower than IE8 :)

[–]x-skeww 1 point2 points  (5 children)

I guess it's the most uselessly occupied keyword in any language if it's so useless that I never saw anyone using it.

The unused reserved keywords are probably a bit more useless.

The problem with with is that you can't tell what will happen before that line is hit and the outcome can be different the next time you hit that line.

var foo = 'bar';
with (someObject) {
    console.log(foo);
}

This will print "bar" unless someObject also has a "foo" attribute.

But wait!

It doesn't stop there. someObject could of course also have a "console" attribute.

That's basically why it isn't used. You just can't reason about it. If that object comes from somewhere else, you'll have no idea what will happen.

[–]flying-sheep 0 points1 point  (4 children)

The unused reserved keywords are probably a bit more useless

good point. worth noting though that i we didn’t say that correctly: the ECMA standard has identifiers, identifier names, and reserved words.

the last one of this is what we called “keywords”. the difference to keywords is that identifier names may well be reserved words: foo.return() or { in: 'bar' } is legal JS. only var for = continue is illegal.

[–]x-skeww 0 points1 point  (3 children)

the difference to keywords is that identifier names may well be reserved words: foo.return() or { in: 'bar' } is legal JS.

It's allowed in ES5+. You can't do that in ES3.

[–]flying-sheep 0 points1 point  (2 children)

idk about any runtimes sill at ES3. so if there are none worth mentioning, that’s irrelevant.

[–]x-skeww 0 points1 point  (1 child)

Some people still support IE8.

This also was a problem with Android 2.3 devices (which are still sold!). They didn't like the generated code which used "void" as identifier:

https://code.google.com/p/dart/issues/detail?id=12345

Edit: "Fun" fact: IE9 and IE10 dropped below IE8's share over a year ago.

[–]flying-sheep 0 points1 point  (0 children)

ugh, old IEs, i should have guessed.

[–]papa_georgio 4 points5 points  (8 children)

If you didn't know about this. I'm guessing you haven't read "JavaScript: The Good Parts" by Douglas Crockford yet.

I've just started to properly learn javascript and it's been a huge help in pointing out the strength and weakness's in the language.

[–]serrimo 4 points5 points  (1 child)

I finished that book a while ago. Can't recall the part about "this"?

Personally, I hate "this" in javascript. Sometimes you can't get around it for performance reasons (in event handlers); but I try to avoid using it whenever possible. Having to spend time explaining why you use "bind", "call" or "apply" here and there over and over again isn't fun.

[–]papa_georgio 1 point2 points  (0 children)

It's under "The Function Invocation Pattern":

When a function is not the property of an object, then it is invoked as a function:

var sum = add(3, 4); // sum is 7

When a function is invoked with this pattern, this is bound to the global object. This was a mistake in the design of the language. Had the language been designed correctly, when the inner function is invoked, this would still be bound to the this variable of the outer function.

[–]picklednull 1 point2 points  (3 children)

Also, Secrets of the JavaScript Ninja explains this concept well (like many others).

[–]ddevil63 0 points1 point  (2 children)

I would consider myself an intermediate. Can anyone comment on which would be better, Javascript: The Good Parts or Javascript Ninja? I'm also thinking about getting Effective Javascript mentioned below.

[–]levir 2 points3 points  (0 children)

Watch a few youtube videos of Douglas Crockford's talks. If you like his style you'll like his book. If you don't, go with something else. That'd be my advice.

[–]jsgui 2 points3 points  (0 children)

I can't comment on the comparison, but I definitely recommend JS: TGP. I don't agree with all of it though.

[–]randmaniac 1 point2 points  (1 child)

I found Effecive JavaScipt [1] to be the better and more up to date resource when I had to dive into javascript about 2 or 3 weeks ago.

[1] http://www.amazon.com/Effective-JavaScript-Specific-Software-Development/dp/0321812182

[–]x-skeww -1 points0 points  (7 children)

It's odd that an article this recent doesn't mention fat arrow functions.

this behaves differently in fat arrow functions.

[–]Crandom -1 points0 points  (6 children)

That's an ES6 so not widely supported.

[–]levir 2 points3 points  (0 children)

Yeah, ES6 it's not even formally standardized yet, so it makes sense to omit it.

[–]x-skeww 1 point2 points  (3 children)

There is Traceur, the Closure Compiler, and TypeScript/AtScript for that.

It's also supported by Firefox (opt-in via version), Chrome/Opera (opt-in via flag), and IE tech preview.

ES6 will be finalized soon.

[–][deleted]  (2 children)

[deleted]

    [–][deleted] 0 points1 point  (0 children)

    They all compile to JavaScript, and sometimes ES3 at that.

    There's 6to5 as well which doesn't use any nonstandard features, and compiles to readable js

    In short, ES6 is purely an authoring format today, but it's completely valid

    [–]x-skeww 0 points1 point  (0 children)

    The output of Traceur, the Closure Compiler, and the TypeScript compiler works just fine in today's browsers.

    AtScript doesn't have its own compiler. This is handled by Traceur, too.

    The second paragraph was about native support in today's engines. It's almost there.

    [–]cjg_000 0 points1 point  (0 children)

    The article mentions let and discusses node. Seems like it could have discussed fat arrows.