Hacker News new | ask | show | jobs
by jlongster 4998 days ago
He's wrong in the "Constructor Invocation" example.

function Foo(type) { this.type = type; return type; }

var bar = new Foo(5);

`bar` DOES equal 5. When you return something in a constructor, it returns it instead of returning the newly constructed object. This is a neat way for constructing different types of things.

And most of his complaints are just because he doesn't understand how `this` scoping works in javascript. If you don't understand something, don't just blame it on "bad patterns". It might not be the most intuitive, but once you learn it, it's fine. Sure, I have to bind `this` to a different function here and there, but these problems are not that bad in real world javascript.

3 comments

> `bar` DOES equal 5

No, it doesn't. Javascript is a bit weird when it comes to return statements inside constructors. `bar` will be equal to `type` only if `(type instanceof Object) == true`. Otherwise, it will be a new object.

    function Foo(type) { this.type = type; return type; }
    console.log(new Foo(/a/));   // Regexp /a/
    console.log(new Foo("a"));   // {type: "a"}
    console.log(new Foo(5));     // {type: 5}
    console.log(new Foo([1,2])); // [1,2]
    console.log(new Foo({a:1})); // {a: 1}
Huh, you're right. I thought I typed that at the REPL and it gave back 5, but obviously I typed the wrong thing.

Almost all cases that I've used this functionality have been to return a different object. I suppose when you say "new" you're supposed to expect an object, which is why it works that way.

a good time to point out that calling Object() without "new" returns a new object. This is often unexpected when creating inheritance schemes that chain the parent constructor.

https://github.com/documentcloud/backbone/pull/1269

Not sure I understand your comment, given the link you gave.

IMHO the return value of calling `Object()` without parameters is exactly what one would expect. Calling it w/ parameters is what I think causes surprising behavior

    var x = {a: 2}
    console.log(x === x)             // true
    console.log(Object(x) === x)     // true
    console.log(new Object(x) === x) // true
For the `Object.call(x)` case, I'd expect it to return a new object (and not x), for the same reason I'd expect [].slice.call(arguments) to return a new array (and not arguments).
[].slice.call(arguments) returning a new argument is fundamentally different because you would not want x.slice(1,2) to modify x in order to produce an appropriate sublist to return. Perhaps it's just me, but I expect a constructor to initialize "this" (optionally returning "this"), but not returning {};
Disagree. To illustrate:

    window.test = 2
    var b = Object.call(window) //this is the same as `var b = window.Object()` and therefore the same as `var b = Object()`
    assert(b.test == 2) //why should this be true?
I realise that everyone is critic, but I am sorry: I understand fully how `this` gets bound and how scoping works in Javasscript. And it sucks!

Scoping: Javascript uses C/Java notation but it does not have block scope, only function scope. That to me seems very misleading.

And with regards to `this`, the way function invocation sets `this` differs totally from method invocation. How can this not be a problem!

> Scoping: Javascript uses C/Java notation but it does not have block scope, only function scope. That to me seems very misleading.

Yes, it is, but we weren't talking about that problem. That is already solved in ES6 with `let`, which is approved and will be available in about a year.

> And with regards to `this`, the way function invocation sets `this` differs totally from method invocation. How can this not be a problem!

Function and method invocation are different things, with different semantics. It's like that in many other languages too. Sure, the way `this` is handles is a problem sometimes, but I think it's overblown.

"Complaints"? Wha? Did we read the same article? Except for a few asides, he wasn't complaining. He was explaining.