10 ms·
A re-introduction to JavaScript
- jongdubois 11y agoI think there's no point trying to avoid memory leaks in older versions of IE. Circular references due to closures are too common and it's not worth messing with your code. IE users are probably used to getting a horrible user experience anyway. I'm sure they can cope with a few browser freezes/crashes every once in a while - They know how to take a beating :p
- drinchev 11y agoThere's definitely no point to avoid them for IE. The point as I see it is that it should be avoided for every browser. Indeed IE's users are having terrible experience anyway, but let's just don't push FF and Chrome to their memory limits, just because we don't care with our code. One of the best parts when I develop client-side web-apps is the debugging and looking close what the garbage collector is doing. For example : I usually don't use `delete` keyword, since I know it might create a node that GC's can't clear.
- xtrumanx 11y agoCan you expand on what you said about the `delete` keyword implications with the GC? I've never heard of that issue.
- Touche 11y agoI haven't either, only that delete will cause code to be de-optimized.
- chris_wot 11y agoI think it affected earlier versions of IE - Douglas Crockford detailed an issue here: http://javascript.crockford.com/memory/leak.html http://javascript.crockford.com/memory/leak.html
- chris_wot 11y agoWhat the hell is wrong with people today? I was hazarding a guess what was being referred to and I get down voted?
- CrystalGamma 11y agoIts main purpose is deleting a property from an object, which is a pretty slow operation on modern JS engines. Unless some code tests for the existence of a property, setting it to null is a better idea.
- tracker1 11y agoI'd suggest undefined over null if you want to effectively remove a property, since JSON.stringify won't serialize those properties... in an array, it will become null. Though, I don't use delete much, I honestly don't worry about it much. In most contexts it's a bit of a premature optimization unless you are in a very low-level tool that will be used for example gaming, video or photo manipulation, there are probably better optimizations to make.
- magicalist 11y agoThe reason this is mentioned (and things like the part about caching array length in your for loop) is that this tutorial was mostly written back in 2006, when things were obviously a bit different with JavaScript. The article has gotten updates since then (check the history), but not many and not to the extent it probably needs. Not sure why it keeps getting linked.
- golergka 11y agoSince you seem to have an understanding of what is wrong with it, care to tell about everything you know that should be updated?
- roryokane 11y agoI would find that helpful. Since the article is a wiki, I would be willing to edit in any suggestions that magicalist makes, if magicalist doesn’t want to bother doing the editing him or herself.
- frik 11y agoIt was very important for IE <=6. Early AJAX web apps like GMail ~2004 were quite hard to get right - avoid most memory JS leaks or the memory consumption got out of hand too fast. That was in the days of 512 MB memory and WinXP.
- tracker1 11y agoI worked on an extjs app for a company where most of the users at the time where IE6 corporate wide (this was several months after IE8 was available. That said, there were such horrible memory leaks with references just in the nature of the application under IE (component<->JS ties wouldn't unwind/gc) it would quickly eat up memory after about half a day of work would need to restart the browser... In the end a lot of people using the application would either have to restart during the day, use portable Firefox, which many actually did. Of course, there are/where many worse things in practice dealing with supporting IE<9 for relatively modern web applications. I'd still rather deal with that, than the v4 browser days.
- Roboprog 11y agoI was stunned when I read the part about hooking the "this page is done now, let's go to another" event to manually clean up memory. (Old) IE worse than failure, indeed.
- efbbbf 11y agohttps://news.ycombinator.com/item?id=7169513 https://news.ycombinator.com/item?id=7169513 https://news.ycombinator.com/item?id=3569893 https://news.ycombinator.com/item?id=3569893 https://news.ycombinator.com/item?id=1524450 https://news.ycombinator.com/item?id=1524450 https://news.ycombinator.com/item?id=601967 https://news.ycombinator.com/item?id=601967
- Roodgorf 11y agoThese are all roughly a year apart and it's a very interesting article. I don't really see a big problem with reposts that far apart to catch newcomers' eye.
- bshimmin 11y agoApart from they wouldn't really be "news", which is supposedly what this site is for (as denoted by the site's name and URL).
- chris_wot 11y agohttps://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html
- bshimmin 11y ago"Please don't insinuate that someone hasn't read" the Hacker News Guidelines...
- chris_wot 11y agoI'm not insinuating, I'm telling you. Incidentally, can you not see the irony of your own statement? Please, stop with your valueless comments. This article is and remains a perfectly valid submission to HN.
- oldmanjay 11y agoAccording to the guidelines, I should charitably interpret that you have read them. Which means, charitably, you are ignoring them.
- serve_yay 11y agoVery nice to see it starts off with a (correct) discussion of JS types! JS devs mostly don't know the actual types in JS, which is pretty crazy if you think about it.
- sergiotapia 11y agoI think 99% of the problems people have with Javascript are not actually types, but `this`. It's the most confusing part about Javascript. This context, var foo scope, what? Why is this value not updating? undefined? What???
- csandreasen 11y agoI actually found the Javascript 'this' keyword more understandable after working with Python. >>> class foo(): ... def test(this, x): ... print this, x ... >>> x = foo() >>> x <__main__.foo instance at 0xb71928ac> >>> x.test(1) <__main__.foo instance at 0xb71928ac> 1 >>> y = foo.test >>> y(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method test() must be called with foo instance as first argument (got int instance instead) >>> y(x,1) <__main__.foo instance at 0xb71928ac> 1 In Python, the reference to the current object is an explicitly declared parameter in the method definition, but the parameter is passed implicitly - the value of "this" is whatever is comes before the period when the method is called. If you call it in any other manner, it throws an unbound method error. Javascript is the same way, but instead of throwing an error it will instead pass 'window' implicitly. The equivalent code in Javascript: function foo() { } foo.prototype.test = function(x) { console.log(this, x); } var x = new foo(); x.test(1); // prints VM1061:4 foo {test: function} 1 var y = x.test; y(1); // prints VM1061:4 Window {top: Window, window: Window, …} 1
- reipahb 11y agoActually, what you get when referencing x.test in Python is a bound method: >>> foo.test <unbound method foo.test> >>> x.test <bound method foo.test of <__main__.foo instance at 0xf74d68ac>> >>> z = x.test >>> z(123) <__main__.foo instance at 0xf74d68ac> 123 I really like this behavior in Python. Unfortunately, JavaScript does not behave the same way, as you see in the last couple of lines in your example. You can however get the same result by manually binding the method to the object: z = x.test.bind(x) // z is: function () { [native code] } z(123) // foo {test: function} 123
- PhineasRex 11y ago"While often derided as a toy" Javascript is not a toy; toys are fun.
- serve_yay 11y agoWhat could be more fun than a language that says the result of dividing by 0 is "Infinity"? It's a hoot!!
- ahoge 11y agoThat's from IEEE 754 (a standard for floating-point arithmetic). `NaN` and -0 exist for the same reason.
- bionsuba 11y agoTo be fair, just because something is a standard doesn't mean it isn't a dumb implementation. Just by testing the programming languages on my computer, I can tell you that Python, C, and D all throw errors rather than allow it, which is the smart thing to do.
- magicalist 11y ago> I can tell you that Python, C, and D all throw errors rather than allow it Python throws an error, but numpy.divide(1., 0) will work just fine (and return inf). I'm not sure why you're saying C throws an error. The behavior of dividing by 0 is undefined by default, but on most machines these days the hardware implements IEE-754 and the C implementation will advertise as implementing IEC 60559, so 1. / 0 will give you inf as well.
- bionsuba 11y agoTrying to compile a test program with Clang threw errors, and bringing up numpy is disingenuous.
- 11y ago
- gildas 11y ago> You can also use the unary + operator to convert values to numbers: + "42"; // 42 > [...] However the "+" operator simply converts the string to NaN if there is any invalid character in it. Being a bit pedantic here, why not recommending the Number function which may be less obscure for beginners? Number("42"); // 42
- arcatek 11y agothe String function is also a nice way to cast a value to a string (using .toString() is unsafe because it may not exist, such as with undefined and null): String(42) === "42". An other thing that could maybe be covered is this specifity: typeof "42" === "string" typeof String(42) === "string" typeof new String(42) === "object" Native constructors are ... fun beasts, to say the least.
- serve_yay 11y agoYes, that's a good suggestion. Boolean works as well, for coercing to boolean of course.
- ahoge 11y agoSince calling constructor functions without `new` is generally an error, I'd rather use `parseFloat`.
- serve_yay 11y ago> Since calling constructor functions without `new` is generally an error The behavior of Number, Boolean, String, and Array is well-defined, it's safe to call them without new. In fact, in the case of String/Boolean/Number, calling them with new will often do something you don't expect. (Calling them with new gives you a Number/String/Boolean object, not primitive, which can cause trouble when you try to compare them with ===, unless you remember to use their `valueOf` method) Also, as noted below, it's possible for objects to not have a `toString` method, so attempting to call it to get the object's value as a string could blow up. So it's actually safer to coerce to string by adding an empty string or passing to String().
- kremlin 11y agoThe article mentions an idiom for iterating over an array. It says 'an even nicer idiom is...' and then it shows it. I just wanted to say that the behaviour of this 'nicer' idiom may not be what's expected - it stops iterating once it hits the first falsy value. I was quite excited actually when I first saw them idiom, until I quickly realized its limitations
- serve_yay 11y agoOh jeez, I just saw that the section you're referring to repeats the old canard about caching the length of an array when iterating over it. Come on, that can't still be good advice. It always struck me as ridiculous to begin with, but almost certainly now it's optimized away. Not to mention the suggestion you're talking about, which I bet would bite programmers for the reason you mention. Seems like a bad idiom, I've personally never seen it in the wild.
- kremlin 11y agothe problem with using it even when you don't have falsy values is that, eventually, you're going to forget that you can't use it when you do have falsy values. You're going to get too comfortable with it, and it's not general-purpose enough. Can't wait for ES6 to no longer be 'experimental', as I'd much prefer to use 'for..of' loops
- tracker1 11y agoHonestly, I'm more excited about some of the ES7 features at this point... I've given in, as much as I dislike transpiling, and using BabelJS for most of my new development, server and client-side. On the server-side async/await are worth their weight in gold... and using lambdas is very nice. I still don't like the ES6 module syntax over node/commonjs require statements though. The only thing to be really mindful of is when you browserify for the client that you don't accidentally include, for example the entire crypto library, buffer or similar shims because they can get very big, very quickly.
- pluma 11y ago
- snorrah 11y agoThe article says to watch out for 0.1 + 0.2 not exactly equalling 0.3 , so as a complete newbie to JavaScript, how do you work around this ?
- Scarbutt 11y agoIs not a JS only thing, investigate how floating point values work.
- MichaelGG 11y agoWell other languages often offer decimal, or higher precision floats, right?
- Scarbutt 11y agoright, but I think he first needs some insight on how IEEE 754 floating point arithmetic works.
- jahewson 11y agoNot really. Most languages don't have a built-in decimal type, it's usually just a library feature. Higher precision floats won't help you either, as adding more decimal places won't make 0.2 == 0.3, it will just make the difference between them slightly smaller.
- pests 11y agoYes, .NET is a good example with a decimal type with: Approximate Range -> (-7.9 x 1028 to 7.9 x 1028) / (100 to 28) Precision -> 28-29 significant digits https://msdn.microsoft.com/en-us/library/364x0z75.aspx https://msdn.microsoft.com/en-us/library/364x0z75.aspx
- pests 11y agoYes, .NET is a good example with a decimal type with Approximate Range -> (-7.9 x 1028 to 7.9 x 1028) / (100 to 28) Precision -> 28-29 significant digits https://msdn.microsoft.com/en-us/library/364x0z75.aspx https://msdn.microsoft.com/en-us/library/364x0z75.aspx
- deleted 11y ago[deleted]
- kelvin0 11y agoRediscover Javascript, by using :TypeScript, CoffeeScript or Node.js and a gazillion of slightly incompatible web frameworks ... I wish DART had been there in the beginning.
- ffn 11y agoWhoa, the closure-based circular reference memory leak thing, is that just an IE issue or is that a language level (anti) feature? I need to know because I've very often done something like: el$ = $('#whatever'); el$.click( function() { el$.find("a").css("color", "red"); } );
- z3t4 11y agoI think it's much easier to forget about "types" and think of objects instead. Trying to divide JavaScript objects into "types" will surely get you frustrated. If you absolutely want to check what "type" an object is, for example a sanity check for arguments passed to a function, you should make your own isMyType(obj) function and not rely on typeof or toString.
- deleted 11y ago[deleted]
- tracker1 11y agoI think if you simply accept that there is no spoon, and that any utensil can be coerced and used as a spoon you will be much happier. In general, the only niggle is when you want a discrete integer value, where zero is an acceptable input, or a string that represents a number coerced into a number.. but anything else to be null. You have to single out falsy values that aren't zero in this case. Other than that one niggle in practice, I've come to truly appreciate the expressive nature that JS actually offers in practice. The additional concepts added in terms of ES6 and ES7 are pretty welcome. Though in practice, I've moved very far away from trying to apply many OO patterns of classes, inheritance, etc in favor of basic object instances, and functions that can be combined/composed. It's pretty nifty all around.
- Nican 11y agoFor the second example on the memory leak section (https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript#Memory_leaks https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re...), wouldn't just changing "el.style" to "this.style" fix the memory leak?
- ww520 11y agoOne caveat not mentioned is that while float is 64 bit floating point number, int is only 53 bit integer, unlike having 64 bit int in most other languages. Yeah, I've got bitten by this before causing a nasty bug.
- thomasfoster96 11y agoAs far as I know 53-bit integers are a bit haphazard in JavaScript - it's best to stick to 32-bit unless you really know what you're doing.
- tracker1 11y agoThe biggest gotchas with whole numbers in JS (IEE754 64-bit floats) is that in JS all bitwise operations are performed on a 32-bit integer under the hood... in practice this means you can do a bitwise operation on anything and it will be coerced into a 32-bit integer, either first via the parseInt(X,10) path, or becomes an empty 0 value. It really isn't unique to JS, and there are several bignum libraries that can/will help.
- deathanatos 11y agoThere is no "int" or "float" (mostly[1]) — there is only Number, which is an IEEE floating point. A literal `1` is a floating point that happens to be precisely representing an integer. "53 bits" happens to be the limit of consecutive integers that you can store in an IEEE double. [1]: 32-bit integers show up under the hood, in expressions such as `5000000000|0`. Both 0 and 5000000000 are precisely represented in JS's Number type, but you cannot (correctly) take a binary OR of the two.
- dorfsmay 11y agoThis is a really good overview. Along the same line but more in depth, I really like Cody Lindley's JavaScript Enlightenment: http://www.javascriptenlightenment.com/ http://www.javascriptenlightenment.com/
- anon3_ 11y agoCool. Did Brendan Eich write it? What's he doing these days? Keep up the good work Mozilla. edit: I see MANY people contributed! You can too! https://developer.mozilla.org/en-US/docs/Mozilla/Connect https://developer.mozilla.org/en-US/docs/Mozilla/Connect. It still would be cool if Eich could act as an "editor" to JS related articles!
- philbo 11y ago"JavaScript is an object oriented..." No it isn't. It has support for OO and you can choose to write code object-oriented if you wish. But equally you can disregard the OO bit quite happily and compose behaviour using closures instead. None of my favourite JS libs are OO, it's a poor abstraction imho.
- totony 11y agoI wish there were more tutorials of this style, for people who are already familiar with programming and just want to know how a language works.