

A re-introduction to JavaScript - hikz
https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

======
jongdubois
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
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
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
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.

------
PhineasRex
"While often derided as a toy"

Javascript is not a toy; toys are fun.

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

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

~~~
bionsuba
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
> _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
Trying to compile a test program with Clang threw errors, and bringing up
numpy is disingenuous.

~~~
yoklov
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.

------
kremlin
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

~~~
serve_yay
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
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
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
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.

------
efbbbf
[https://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
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.

~~~
andrewpe
I've only been here for a couple of months and this was nice to see.

------
gildas
> 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

~~~
bluesnowmonkey
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
Bitwise operations don't produce Numbers (f64), but signed integers (i32).

~~~
ougawouga
> produce...signed integers

Well, except for right logical shifts.

------
serve_yay
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
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
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
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

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

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

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

~~~
jahewson
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.

------
philbo
"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
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/](http://www.javascriptenlightenment.com/)

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

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

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

~~~
thomasfoster96
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
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_
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](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
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.

