Settings

Theme

A re-introduction to JavaScript

developer.mozilla.org

290 points by hikz 11 years ago · 114 comments

Reader

jongdubois 11 years ago

I 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

  • magicalist 11 years ago

    The 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 11 years ago

      Since you seem to have an understanding of what is wrong with it, care to tell about everything you know that should be updated?

      • roryokane 11 years ago

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

  • drinchev 11 years ago

    There'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 11 years ago

      Can you expand on what you said about the `delete` keyword implications with the GC? I've never heard of that issue.

      • Touche 11 years ago

        I haven't either, only that delete will cause code to be de-optimized.

        • CrystalGamma 11 years ago

          Its 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 11 years ago

            I'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.

        • chris_wot 11 years ago

          I think it affected earlier versions of IE - Douglas Crockford detailed an issue here:

          http://javascript.crockford.com/memory/leak.html

          • chris_wot 11 years ago

            What the hell is wrong with people today? I was hazarding a guess what was being referred to and I get down voted?

  • frik 11 years ago

    It 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 11 years ago

      I 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 11 years ago

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

PhineasRex 11 years ago

"While often derided as a toy"

Javascript is not a toy; toys are fun.

  • yarrel 11 years ago

    I like JavaScript but that did make me laugh.

  • serve_yay 11 years ago

    What could be more fun than a language that says the result of dividing by 0 is "Infinity"? It's a hoot!!

    • ahoge 11 years ago

      That's from IEEE 754 (a standard for floating-point arithmetic). `NaN` and -0 exist for the same reason.

      • bionsuba 11 years ago

        To 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 11 years 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 11 years ago

            Trying to compile a test program with Clang threw errors, and bringing up numpy is disingenuous.

            • yoklov 11 years ago

              Are you sure you were using floating point math? Compiling 1.0 / 0.0 should not give errors or warnings. 1 / 0 will, on the other hand.

      • serve_yay 11 years ago

        I know, I was just joshing! Man, you guys really didn't like that one. Personally I enjoy taking a moment now and then to reflect on some of the sillier aspects of JS. This is because I love JS, not because I hate it.

kremlin 11 years ago

The 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

  • BinaryIdiot 11 years ago

    Yeah and not a big fan of them saying you can do for...in on an array while casually mentioning the limitation of doing such. I would consider it far better practice to NEVER iterating over an array with for...in.

  • serve_yay 11 years ago

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

    • pluma 11 years ago

      I think nearly every JS engine now optimizes `for (...;i < arr.length;...)` -- I'm nearly 100% sure V8 does and fairly certain Firefox's and ModernIE's do as well.

      In fact, even `for` is likely an over-optimization. In nearly all JS code you can get away with just using `forEach` (or its friends).

      • thomasfoster96 11 years ago

        forEach is awfully slow compared to a for statement if you're dealing with numbers - less so with strings/objects, but it's still noticeable (like 10x whenever I've tested it at best).

        Caching the array length still gives you a small speed boost in most browsers, but it's probably an over optimisation unless you're doing something really intensive.

        • pluma 11 years ago

          If you're doing number crunching, yes, don't use forEach.

          If you're just writing ordinary business code (i.e. in 80% of all code out there), by all means, please use forEach and friends.

          Besides, if you're doing number crunching in JS, you probably want to stick to ASM.js anyway.

        • jaredsohn 11 years ago

          I think a big reason to cache the array length within interviews (for cases when it isn't already cached) is that to not do so can often increase the complexity of a solution by a factor of O(n).

    • kremlin 11 years ago

      the 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 11 years ago

        Honestly, 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.

    • jaredsohn 11 years ago

      >old canard about caching the length of an array when iterating over it

      I think there are still places where you need to do this (please correct me if wrong, or mention some other cases):

      - when iterating over DOM nodelists in JS (why doesn't the browser cache this as well?)

      - if using strlen in C/C++ (for the latter, you should use string.length() instead).

  • wwweston 11 years ago

    Also seems weird that they don't mention `forEach`.

    (Sure, IE<9 is a caveat, but all the Array iteration methods are the easiest things to shim and if you're targeting below IE9 chances are pretty good it's not the first shim you'd be using.)

  • roryokane 11 years ago

    I improved the wording:

    “A nicer-looking but limited idiom is:”

    MDN documentation is on a wiki. You can just edit the page.

efbbbf 11 years ago

https://news.ycombinator.com/item?id=7169513

https://news.ycombinator.com/item?id=3569893

https://news.ycombinator.com/item?id=1524450

https://news.ycombinator.com/item?id=601967

  • Roodgorf 11 years ago

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

serve_yay 11 years ago

Very 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 11 years ago

    I 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 11 years ago

      I 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 11 years ago

        Actually, 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
      • pluma 11 years ago

        I came (back) to JS after doing a lot of Python and I think that may have helped understanding `this` in JS.

        Note that the behaviour of `this` defaulting to `window` (or `global`) is only the legacy behaviour. You should be using strict mode (there's really no justification not to -- except for extremely rare edge cases, e.g. having to delete global variables without having a reliable reference to the global object other than `this`).

        In strict mode, `this` would be undefined. As expected, if you consider `x.y()` syntactic sugar for `x.y.call(x)` (and therefore `z()` syntactic sugar for `z.call(undefined)`).

        Under the hood, invoking a function translates to a call of the functions `[[Call]]` method, which takes an explicit `this` just like `Function.prototype.call` does.

      • tracker1 11 years ago

        I find that testing works better when I define my functions separately from binding in objects.

          var foo = {
            doSomething:(...argv)=doSomethingMethod(foo, argv)
          };
          return foo;
        
        In this way, the execution is always predictable, as I avoid the use of this altogether... It's my one niggle with koa, that it uses this (execution context) as the request/response context. I tend to it in practice.

        It's similar to what Crockford now presents as a preferred approach in dealing with having context for functions... I just like discrete functions that can be tested independently of their execution context... by passing the context as a parameter, this becomes explicit... with binding, the process becomes transparent.

    • lewisl9029 11 years ago

      Using jspm, SystemJS and Babel for my latest project, and simply using let universally over var and arrow functions over anonymous functions has made this aspect of JavaScript behave like any sane language would.

      I simply don't ever need to think about it anymore.

    • serve_yay 11 years ago

      I agree, `this` is a disaster. But, I just can't hardly think of another language where the people working in it mostly don't know the types. (Well, OK, PHP devs probably mostly don't)

      And I don't just mean run-of-the-mill blub programmers who dabble in jQuery, I mean some of the best devs I've ever seen in any language. I had a self-proclaimed JS expert tell me that JS has integers and floats as distinct types. Even the people I work with every day who are fantastic did not know that function and array are not types.

      Of course, things like `typeof` don't help the situation, so I don't put the blame squarely on programmers' shoulders. And obviously you can get a lot done without knowing that, technically, functions are just objects that can be called. But it still strikes me as kinda crazy.

      • barrkel 11 years ago

        "technically, functions are just objects that can be called"

        How can you create an object which can be called like a function, but will respond to 'typeof' with 'object' rather than 'function'?

        What happens when you try to call an object - what's the error? Try it, in a few of your favourite javascript interpreters:

            ({})()
        
        It seems clear to me that functions are more than "just" objects in JS. You can't start out with a random {} and turn it into a function. JS functions are a subtype of JS objects, but they are a distinct type. You can't substitute an object where a function is expected - you get a type error - but you can substitute a function where an object is expected.
        • serve_yay 11 years ago

          > How can you create an object which can be called like a function, but will respond to 'typeof' with 'object' rather than 'function'?

          You can't, by definition. Here is the relevant section of the ECMAScript 5 spec: http://www.ecma-international.org/ecma-262/5.1/#sec-11.4.3

          Basically, an object which implements call will always cause `typeof` to return "function". But the broader point is that `typeof` will lie to you and you shouldn't trust it for, you know, determining the types of values. (For example, the type of null is null, but `typeof null` returns "object".)

          As I noted above, this behavior of `typeof` is part of what causes the confusion around types in JS devs.

          > You can't substitute an object where a function is expected - you get a type error - but you can substitute a function where an object is expected.

          This is true, but not inconsistent with the notion that functions are objects which can be called. I encourage you to read the spec I linked above, or a draft of ES6.

          • barrkel 11 years ago

            There's types as defined in a spec, and types according to type theory.

            In short, I think the spec is incorrect in its use of the concept of types; or incomplete.

            You'll note that the spec uses the concept of "internal properties" to distinguish between the different things one can do with values. From a type theory perspective, these internal properties and the implied permitted operations come close to type definitions. It's a matter of perspective, then, when one is using the word 'type' as defined by a particular language's spec, or 'type' as in programming language pragmatics / type theory POV. For the generalist programmer who knows more than one language, a broader concept of types is usually more useful.

            Further, the spec uses these internal properties solely to define the semantics of the language, and they are not necessarily visible artifacts of any implementation. Talking about them as if they were concrete confuses the map with the territory.

          • foldr 11 years ago

            >Basically, an object which implements call will always cause `typeof` to return "function".

            Are there any implementations which actually do this? In Node:

            typeof({ call: function () { } }) --> 'object'

            ({ call: function () { } })() --> TypeError: object is not a function

    • buckbova 11 years ago
    • yulaow 11 years ago

      and 99% of those 99% problems can easily be solved with the correct use of .bind() or .apply().

    • chris_wot 11 years ago

      Especially when you need to do something like:

        var that = this;
      • bryanlarsen 11 years ago

        That's not generally necessary in ES6 when you use "=>" to define functions. Javascript is getting better...

        • neurosnap 11 years ago

          What happens when you nest anonymous functions? Would you have to use the arrow operator at every level?

        • chris_wot 11 years ago

          It's really a minor criticism and I know ES6 resolves the issue :-)

          • chris_wot 11 years ago

            Through bind of course, for the silly person who downvote me. Helps to have strict mode on. Happy to have educated you!

      • sergiotapia 11 years ago

        Looking at you Ember. Ugh!

            var controller = this;
            
        Every time!
        • chris_wot 11 years ago

          They have to. There's a bug in the JavaScript spec that makes you do this :-) they are perfectly correct in doing what they are doing, if they didn't then funny thing would start to happen. Sad, but true.

          • chris_wot 11 years ago

            Uh, what's the reason for the downvote?

            • oldmanjay 11 years ago

              Probably because when you editorialize in your comment, you may get an adverse reaction.

              • chris_wot 11 years ago

                Not the first to complain about this behaviour. In fact, if you run in strict mode now, ES5 requires you to use bind, call or apply - it won't box this to the global object but will return undefined.

                Why do you think they decided to do this? Strict mode is to allow folks to transition their code to the new standard - and the new standard has made this decision to fix a flaw in JavaScript - it acknowledges its a hack to return the global object in this case.

                So I'm less editorialising and more pointing out what is already known. Hope this helps.

            • coldtea 11 years ago

              Perhaps that the reason for that is not some "bug" in JS?

              • chris_wot 11 years ago

                Except that for many, it is. If you extract a function in an object and allocate it to a global function, and that function calls on "this", then it's fairly obvious that the function cares about the object and not the "this" of the current scope.

                It's why ES5 has bind to get around this.

                Example from MDN [1]

                  this.x = 9; 
                  var module = {
                    x: 81,
                    getX: function() { return this.x; }
                  };
                  
                  module.getX(); // 81
                  
                  var getX = module.getX;
                  getX(); // 9, because in this case, "this" refers to the global object
                
                  // Create a new function with 'this' bound to module
                  var boundGetX = getX.bind(module);
                  boundGetX(); // 81
                
                To make the above example work without bind, you need to take a copy of the reference to this, And use that copy. Thus the kludge:

                  var module = {
                    x: 81,
                    that: this,
                    getX: function() { return that.x; }
                  };
                
                Of course, if you run in strict mode (ES5) the original example will return undefined, because you are now expected to specify this via call, apply or bind.

                1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

gildas 11 years 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
  • tracker1 11 years ago

    If you use a double NOT ~~"foo" you will always get a finite int32 value... which is useful when you can use 0 as a "default" representation. For that matter, all bitwise operations will coerce a value to an int32 representation. Which is something to be aware of, if you want larger integer values (< 2^53 - 1 and > -2^53 + 1).

  • hajile 11 years ago

    Number() also converts to NaN if it's not a number though I would still avoid the + operator here because it is code smell (looks like you forgot your variable to concat).

    Number automatically accepts exponent notation and auto-converts to hex (ignoring octal). parseInt() auto-converts hex and octal unless a radix is specified, but it also ignores the remaining non-number characters at the end of the string.

    There isn't a single method that does whatever you want.

  • arcatek 11 years ago

    the 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.
  • bluesnowmonkey 11 years ago

    Another way to cast to a Number is the bitwise-or operator. It has the useful property of always yielding a number.

        '42' | 0;      // 42
        NaN | 0;       // 0
        null | 0;      // 0
        undefined | 0; // 0
        false | 0;     // 0
        true | 0;      // 1
    • eddyb 11 years ago

      Bitwise operations don't produce Numbers (f64), but signed integers (i32).

    • Touche 11 years ago

      It always yields an integer, so it's useful if you know you want an integer.

  • Bahamut 11 years ago

    Correct me if I'm wrong, but I thought that the unary operator and the Number constructor yield equivalent results?

  • ahoge 11 years ago

    Since calling constructor functions without `new` is generally an error, I'd rather use `parseFloat`.

    • serve_yay 11 years 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().

      • ahoge 11 years ago

        > The behavior of Number, Boolean, String, and Array is well-defined, it's safe to call them without new.

        ES6 is packed with weird but well-defined things.

        The problem is that calling a constructor function (a PascalCase'd function) without `new` looks like an error because it generally is an error. To make matters worse, without closely examining that function, you cannot tell if it's an error.

        I do know that `Number()` happens to be one of those constructor functions which not only work without `new`, it also happens to behave differently when `new` is missing. It does not return an object. It returns a primitive.

        Someone who doesn't know about this unusual secondary function will waste some time if they spot this apparent mistake.

        Now, to defuse this time-wasting trap, you could either add a comment... or just do the sensible thing and write it in a way which does not require a comment.

        • serve_yay 11 years ago

          That's fair, I just find them super useful in various situations, for example filtering over an array with Boolean to remove falsey values.

  • serve_yay 11 years ago

    Yes, that's a good suggestion. Boolean works as well, for coercing to boolean of course.

  • amelius 11 years ago

    Because Number(...) uses more bytes on the wire.

ffn 11 years ago

Whoa, 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 11 years ago

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

  • tracker1 11 years ago

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

snorrah 11 years ago

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

  • EpicDavi 11 years ago

    This is not a huge problem as if you are outputting the floating point number, you would probably want to round it anyways. The biggest 'gotcha' is when doing equality comparisons between these numbers.

    Consider the following:

        .1 + .2 == .3 // false
    
    The way to 'get around' this is to have a value (usually called an epsilon) that is relative in magnitude to the numbers being compared. In this example, a value like .00001 as epsilon should work fine.

    Anyways, all you have to do is check if the absolute difference of the numbers is less than the epsilon:

        var a = .1 + .2, b = .3, epsilon = .00001;
        console.log(Math.abs(a-b)<epsilon); // true
    
    In short, try to not put yourself in a situation where you have to compare equality with doubles.
  • jahewson 11 years ago

    Floating point numbers in any language are inaccurate, if you're performing say, financial calculations then you can use fixed point numbers by using scaled integers. For example:

        var SCALE = 100; // 0.01
        
        var a = 0+1 * SCALE;  // e.g. 2.5 would be 2+5 * SCALE
        var b = 0+2 * SCALE;
        
        if (a + b == 0+3 * SCALE) {
          // this will work...
        }
    
        console.log(a / SCALE);
  • Scarbutt 11 years ago

    Is not a JS only thing, investigate how floating point values work.

    • MichaelGG 11 years ago

      Well other languages often offer decimal, or higher precision floats, right?

      • jahewson 11 years ago

        Not 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 11 years ago

        Yes, .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

      • Scarbutt 11 years ago

        right, but I think he first needs some insight on how IEEE 754 floating point arithmetic works.

  • Roboprog 11 years ago

    See if there is a fixed precision arithmetic library for JS? (similar to BigDecimal in Java / Groovy)

    Homework: 1) Google for such; 2) see which one doesn't suck.

    • vorg 11 years ago

      Groovy is a heavily marketed programming language that uses BigDecimal, just like its sister dynamic languages Clojure, Rhino/Nashorn, and Xtend also do. Only Java actually ships BigDecimal.

      • Roboprog 11 years ago

        Yeah, I get that the base JRE is what actually provides the BigDecimal class in this case -- the other languages just use it. (as the default "decimal"-numeric type in the case of Groovy, rather than [Dd]ouble)

philbo 11 years 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.

dorfsmay 11 years ago

This 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/

Nican 11 years ago

For the second example on the memory leak section (https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re...), wouldn't just changing "el.style" to "this.style" fix the memory leak?

totony 11 years ago

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

ww520 11 years ago

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

  • deathanatos 11 years ago

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

  • thomasfoster96 11 years ago

    As 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 11 years ago

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

anon3_ 11 years ago

Cool. 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. It still would be cool if Eich could act as an "editor" to JS related articles!

kelvin0 11 years ago

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

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection