Live data from Hacker News

Javascript Constructors and Prototypes

tobyho.com

41–50 of 55 posts

Re: Javascript Constructors and Prototypes

#41
post #5

Earlier quoted context omitted.

Did you see the article he linked about why he doesn't use them? http://mislav.uniqpath.com/2010/05/semicolons/ Not reading an article because of that would be like not reading other code because it uses 2 spaces for tabs instead of 4. Makes no difference to the language, only to you.

The thing is, semicolons do make a difference with JavaScript. It's now 404ing, but there was a pretty well-known argument on one of Twitter Bootstrap's GitHub issues[1]. The Bootstrap guys didn't use semicolons, and it caused problems when minifying the code. It's an edge case, I know, but it was a problem. I never understood the whole anti-semicolon thing anyway. It just seems really hipster to me. Use CoffeeScript…

I've always equated javascript without semi-colons with missing comments and poor commit messages. It's just inconsiderate to other developers who have to read your code.

I understand that it is a "feature" of javascript (misfeature in my opinion), but the point that "everyone else does it is not a good argument" is false. We've got like 15 years of javascript written with semicolons. Stop being an inconsiderate prick and just friggin write the code like everyone else!

Don't be that guy (or gal). Comment your code. Write good commit messages. Use semicolons in your javascript.

Re: Javascript Constructors and Prototypes

#42
post #35

This article does two things that are very dangerous, and never mentions the reasons why they're dangerous. * Messing with Function's prototype is very strongly frowned upon. It's tantamount to setting global variables. At the very least, give that definition an if (!Function.new) guard to prevent redefining another implementation that another script (or the browser!) has already given. * Adding methods in the constr…

"In the first version, each time you create a person, a new sayHi function will be created for him, where as in the second version, only one sayHi function is ever created, and is shared amongst all persons that are created - because Person.prototype is their parent. Thus, declaring methods on the prototype is more memory efficient."

Ah, you're right, I missed that. Small amount of bile revoked.

But it should have been MUCH more strongly emphasized as the only way to do it, unless you have a very good reason, not tucked down in the bottom as "oh, if you feel like it, here's a trick to make your code a little better." Especially in a tutorial that's meant for beginners in JS.

Re: Javascript Constructors and Prototypes

#43

This article does two things that are very dangerous, and never mentions the reasons why they're dangerous. * Messing with Function's prototype is very strongly frowned upon. It's tantamount to setting global variables. At the very least, give that definition an if (!Function.new) guard to prevent redefining another implementation that another script (or the browser!) has already given. * Adding methods in the constr…

> If you define this.sayHi in the constructor, then each Person you create gets its own copy of the function, making every Person heavier in memory.

Does anyone know whether this is true for more sophisticated JS engines like v8? I seem to recall reading something like that, that it detects that it is the same function, but I might be misremembering it.

Re: Javascript Constructors and Prototypes

#44

This article does two things that are very dangerous, and never mentions the reasons why they're dangerous. * Messing with Function's prototype is very strongly frowned upon. It's tantamount to setting global variables. At the very least, give that definition an if (!Function.new) guard to prevent redefining another implementation that another script (or the browser!) has already given. * Adding methods in the constr…

> If you define this.sayHi in the constructor, then each Person you create gets its own copy of the function, making every Person heavier in memory. Does anyone know whether this is true for more sophisticated JS engines like v8? I seem to recall reading something like that, that it detects that it is the same function, but I might be misremembering it.

[deleted]

Re: Javascript Constructors and Prototypes

#45
post #22

Earlier quoted context omitted.

My interpretation of "hipster" is being different because you think it's cool to be different. Being different because you think it's a better approach is called "making progress", either because you'll be proven right or proven wrong. I've thought about the de-facto standard way a lot and I think that it does nothing to avoid bugs while potentially misleading a coder about the language. Therefore I think it's worse.…

Nobody has any good reasons that apply to most people, both for and against semicolons. There really isn't a huge difference in either style except in rare cases. > The only reason I follow the de-facto standard is because the time spent arguing about it with my peers is better spent getting work done. Which is why that is an excellent reason. Standards are useful, so if there is one, stick to it. If there is no reas…

Please let us know of one equivalent using semicolons for this semicolon-less bug:

  a = b + c
  (d + e).print()
Which is evaluated as

  a = b + c(d + e).print();
Taken straight out of http://mislav.uniqpath.com/2010/05/semicolons/

> Standards are useful, so if there is one, stick to it. If there is no reason to go against the standard, then don't.

Bingo. I think this is another reason to stick with the standard.

Re: Javascript Constructors and Prototypes

#46
post #39
post #37

Earlier quoted context omitted.

>If the code currently works, then they can read it, and infer that whatever precedence the operators have is the correct one for producing the result the code produces. If "a + b * c" is producing 17 where (a=2,b=3,c=5), then you know that your language makes multiplication precede addition. By that logic why bother using a font in which * and + look like different symbols? Heck, why read the code at all? If the cod…

There is a fundamental difference. When you read "a + b * c"--and then test your assumption of what it does in a REPL--the result is a learning moment where that knowledge now sticks to you; from then on, you know which of the two operators come first. You only have to do it once. On the other hand, "using a font in which * and + look like [the same symbol]" means never being able to recognize the pattern, which mean…

>When you read "a + b * c"--and then test your assumption of what it does in a REPL--the result is a learning moment where that knowledge now sticks to you; from then on, you know which of the two operators come first. You only have to do it once.

If you're good at memorizing essentially arbitrary rules then you only have to do it once. For +/* you can argue that the precedence is standard in the domain language (mathematics), but in C-like languages there are often a dozen operators with their order, and there's no natural reason why >> should be higher or lower than /.

>The equivalent for Haskell is "find a Mathematical domain isomorphic to your problem domain; import a set of new operators which match the known Mathematical syntax of that domain; and then state your problem in terms of that Mathematical domain by using those operators." In either of these cases, nobody can really be expected to just jump in and read the code without looking something, or a lot of somethings, up.

Sure - code is written in the language of the domain. If you don't know what an interest rate calculation is then even the best-written implementation won't be readable to you. But that domain terminology should make sense (indeed a large part of understanding a field is understanding its terminology), whereas many language precedence rules don't - they're completely arbitrary, there's no way to derive them from first principles if you forget.

I'd argue that a language where you don't have to memorize a precedence list (such as Lisp - the precedence is always explicit from the syntax, one simply can't write (+ a b * c - so I'm kind of surprised you mention it). I'm surprised if Haskell is different in this regard) is, all other things being equal, better than a language where you do have to memorize a precedence list. But rather than having to write a whole new language, it's more lightweight to form a "dialect" by declaring "we will write C (or whatever), but only use constructs that do not require memorizing the precedence table".

Re: Javascript Constructors and Prototypes

#47

This article does two things that are very dangerous, and never mentions the reasons why they're dangerous. * Messing with Function's prototype is very strongly frowned upon. It's tantamount to setting global variables. At the very least, give that definition an if (!Function.new) guard to prevent redefining another implementation that another script (or the browser!) has already given. * Adding methods in the constr…

> If you define this.sayHi in the constructor, then each Person you create gets its own copy of the function, making every Person heavier in memory. Does anyone know whether this is true for more sophisticated JS engines like v8? I seem to recall reading something like that, that it detects that it is the same function, but I might be misremembering it.

I don't know, but I would suspect it's still the case, because doing anything else would require a lot of analysis of the code's behavior. In order to safely merge all those definitions into one, the engine would have to know:

* That the function in question never accesses anything in its closure that could be different for each construction

* That hasOwnProperty() is never called on the object to check which way the method is declared (alternatively, remember that it had done this optimization, and spoof the return value)

* That the function is never used as a constructor. Otherwise, Person could update sayHi's prototype and wind up changing its effects for all Persons, where it was supposed to create a customized inner class.

And if you think any of these are easy, remember that you can get a pointer to that function via the following:

  var a = 'say', b = 'hi'
  var sayHi = (new Person)[a + b]

Re: Javascript Constructors and Prototypes

#48
post #5

Earlier quoted context omitted.

Did you see the article he linked about why he doesn't use them? http://mislav.uniqpath.com/2010/05/semicolons/ Not reading an article because of that would be like not reading other code because it uses 2 spaces for tabs instead of 4. Makes no difference to the language, only to you.

The thing is, semicolons do make a difference with JavaScript. It's now 404ing, but there was a pretty well-known argument on one of Twitter Bootstrap's GitHub issues[1]. The Bootstrap guys didn't use semicolons, and it caused problems when minifying the code. It's an edge case, I know, but it was a problem. I never understood the whole anti-semicolon thing anyway. It just seems really hipster to me. Use CoffeeScript…

The link to the issue you mention is broken because the bootstrap repository moved from twitter to twbs. The new link is https://github.com/twbs/bootstrap/issues/3057.

Also note, that ultimately regardless of personal semicolon preference, this was an issue because of a parsing bug in JSMin. It was fixed in JSMin with this commit[0]. Other minifiers such as Closure and YUI did not exhibit any issues with the code as it had been written.

[0] https://github.com/douglascrockford/JSMin/commit/5ca277ea452...

Re: Javascript Constructors and Prototypes

#49
post #3

I used the prototype mechanism several times when debugging a script that I couldn't easily change source code for. I just typed: SomeClass.prototype.someMethod Which outputs the methods source. Then you can add some debug code like console.log(xxx) or even fix a simple bug, copy the whole thing and set it again: SomeClass.prototype.someMethod = function ... Voila! Hot code push without an IDE. While that's obviously…

My favorite trick along those lines:

  var cache = SomeClass.prototype.someMethod;
  SomeClass.prototype.someMethod = function () {
    debugger; // or `throw "stacktrace"`
    cache.apply(this, arguments)
  }
Inserts a stack trace right in the middle of executing someone else's code, which is nice for tracking down why/when that function gets called if documentation is poor, without changing functionality.

Re: Javascript Constructors and Prototypes

#50
I'm bracing for the downvote, but I'm going to say this anyway: are we all taking crazy pills?

I understand that we're more or less stuck with JavaScript, but this is nuts. JS has got to be one of the least intuitive, cobbled together languages I've ever had to work with. In what other language are people still having holy wars over how to separate statements?

Why the heck would a constructor be a regular function if calling it without new pollutes the global namespace? JS gives us prototypes so that we can have inheritance! Great, but that doesn't actually give us a simple ability to call super. Using functions as everything is fine and good, until you have to shoehorn all the functionality you actually need into mysterious constructs like prototype, new, and apply. When the symmetries are so half-assed, at some point, it seems to me to make way more since to stop overloading the same language construct and make separate constructs for separate uses.

And don't even get me started on implicit variable declaration, function hoisting, the double-equals, for...in, the necessity of self-calling functions, etc.

Thank God we have libraries and alternative syntaxes now that more or less smooth over these issues and coerce the programmer into writing reasonable JS code, because green field JS is a complete quagmire. Are we seriously incapable of doing better?

Post reply on HN