w3resource

JavaScript Tutorial

What is a Script ?

A script is an executable list of commands like macro or batch file created by a scripting language. Scripts (like PHP, Perl) which are executed on a web server are called server-side scripts and scripts (like JavaScript) which are executed on user's computer, interpreted by the browser is called client-side scripts.

javascript logo

What is JavaScript ?

JavaScript is a cross-platform, object-oriented scripting language developed by Netscape. JavaScript was created by Netscape programmer Brendan Eich.

It was first released under the name of LiveScript as part of Netscape Navigator 2.0 in September 1995. It was renamed JavaScript on December 4, 1995. As JavaScript works on the client side, It is mostly used for client-side web development.

JavaScript is designed for use on web pages and closely integrated with HTML. JavaScript can create applications which run in the browsers such as IE, Opera, FireFox, Google Chrome and other. Netscape submitted JavaScript to ECMA International for standardization resulting in the standardized version named ECMAScript.

JavaScript and Java

JavaScript and Java are similar in some ways but fundamentally they are different. Java is a programming language developed by Sun Microsystems, Inc. and JavaScript is a scripting language developed by Netscape. Java is a server-side and static type language. JavaScript is a client-side, dynamically typed language. Java programs are compiled on the server and run on almost every platform without distribution of source code whereas scripts written in JavaScript are placed inside a HTML document and interpreted by the browser. The syntax, reserved-words of JavaScript and Java are also different.

JavaScript compares to Java

JavaScript Java
JavaScript is used for front-end web development (for example field level validation in a HTML form). Java is used as a back-end language within a web environment.
Interpreted (not compiled) by the client. Compiled bytecodes downloaded from the server, executed on the client.
Object-oriented. No distinction between types of objects. Inheritance is through the prototype mechanism, and properties and methods can be added to any object dynamically. Class-based. Objects are divided into classes and instances with all inheritance through the class hierarchy. Classes and instances cannot have properties or methods added dynamically.
Variable data types are not declared (loose typing). Variable data types must be declared as Java maintains strong type checking.
Cannot automatically write to hard disk. Cannot automatically write to hard disk.

Features of the w3resource JavaScript Tutorial

In this series of tutorials, we have covered JavaScript 1.5+ in detail. While creating this, we have taken care that learners can master the basics of JavaScript.

Here is a list of features we have included in all of the chapters :

  • We have started with a clear and simple description.
  • We have given a Syntax/Usage so that you can remember how to write it.
  • Example(s) to show how the associated concept is implemented.
  • We have shown the Output of the usage.
  • View the example in a browser.
  • Exercise to practice with our Online Practice Editor.
  • Pictorial presentation to help you to understand the concept better.
  • Since the browser is an issue while executing JavaScript, we have shown which browser support which script.

Next: JavaScript Overview



JavaScript: Tips of the Day

For each over an array in JavaScript.

TL;DR

  • Don't use for-in unless you use it with safeguards or are at least aware of why it might bite you.
  • Your best bets are usually
    • a for-of loop (ES2015+ only),
    • Array#forEach (spec | MDN) (or its relatives some and such) (ES5+ only),
    • a simple old-fashioned for loop,
    • or for-in with safeguards.

But there's lots more to explore, read on...

JavaScript has powerful semantics for looping through arrays and array-like objects. I've split the answer into two parts: Options for genuine arrays, and options for things that are just array-like, such as the arguments object, other iterable objects (ES2015+), DOM collections, and so on.

I'll quickly note that you can use the ES2015 options now, even on ES5 engines, by transpiling ES2015 to ES5. Search for "ES2015 transpiling" / "ES6 transpiling" for more...

Okay, let's look at our options:

For Actual Arrays

You have three options in ECMAScript 5 ("ES5"), the version most broadly supported at the moment, and two more added in ECMAScript 2015 ("ES2015", "ES6"):

  1. Use forEach and related (ES5+)
  2. Use a simple for loop
  3. Use for-in correctly
  4. Use for-of (use an iterator implicitly) (ES2015+)
  5. Use an iterator explicitly (ES2015+)

Details:

1. Use forEach and related

In any vaguely-modern environment (so, not IE8) where you have access to the Array features added by ES5 (directly or using polyfills), you can use forEach (spec | MDN):

var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

forEach accepts a callback function and, optionally, a value to use as this when calling that callback (not used above). The callback is called for each entry in the array, in order, skipping non-existent entries in sparse arrays. Although I only used one argument above, the callback is called with three: The value of each entry, the index of that entry, and a reference to the array you're iterating over (in case your function doesn't already have it handy).

Unless you're supporting obsolete browsers like IE8 (which NetApps shows at just over 4% market share as of this writing in September 2016), you can happily use forEach in a general-purpose web page without a shim. If you do need to support obsolete browsers, shimming/polyfilling forEach is easily done (search for "es5 shim" for several options).

forEach has the benefit that you don't have to declare indexing and value variables in the containing scope, as they're supplied as arguments to the iteration function, and so nicely scoped to just that iteration.

If you're worried about the runtime cost of making a function call for each array entry, don't be; details.

Additionally, forEach is the "loop through them all" function, but ES5 defined several other useful "work your way through the array and do things" functions, including:

  • every (stops looping the first time the callback returns false or something falsey)
  • some (stops looping the first time the callback returns true or something truthy)
  • filter (creates a new array including elements where the filter function returns true and omitting the ones where it returns false)
  • map (creates a new array from the values returned by the callback)
  • reduce (builds up a value by repeatedly calling the callback, passing in previous values; see the spec for the details; useful for summing the contents of an array and many other things)
  • reduceRight (like reduce, but works in descending rather than ascending order)
  • Use a simple for loop

    Sometimes the old ways are the best:

    var index;
    var a = ["a", "b", "c"];
    for (index = 0; index < a.length; ++index) {
        console.log(a[index]);
    }
    

    If the length of the array won't change during the loop, and it's in performance-sensitive code (unlikely), a slightly more complicated version grabbing the length up front might be a tiny bit faster:

    var index, len;
    var a = ["a", "b", "c"];
    for (index = 0, len = a.length; index < len; ++index) {
        console.log(a[index]);
    }
    

    And/or counting backward:

    var index;
    var a = ["a", "b", "c"];
    for (index = a.length - 1; index >= 0; --index) {
        console.log(a[index]);
    }
    

    But with modern JavaScript engines, it's rare you need to eke out that last bit of juice.

    In ES2015 and higher, you can make your index and value variables local to the for loop:

    let a = ["a", "b", "c"];
    for (let index = 0; index < a.length; ++index) {
        let value = a[index];
        console.log(index, value);
    }
    //console.log(index);   // would cause "ReferenceError: index is not defined"
    //console.log(value);   // would cause "ReferenceError: value is not defined"
    

    And when you do that, not just value but also index is recreated for each loop iteration, meaning closures created in the loop body keep a reference to the index (and value) created for that specific iteration:

    let divs = document.querySelectorAll("div");
    for (let index = 0; index < divs.length; ++index) {
        divs[index].addEventListener('click', e => {
            console.log("Index is: " + index);
        });
    }
    

    If you had five divs, you'd get "Index is: 0" if you clicked the first and "Index is: 4" if you clicked the last. This does not work if you use var instead of let.

    3. Use for-in correctly

    You'll get people telling you to use for-in, but that's not what for-in is for. for-in loops through the enumerable properties of an object, not the indexes of an array. The order is not guaranteed, not even in ES2015 (ES6). ES2015+ does define an order to object properties (via [[OwnPropertyKeys]], [[Enumerate]], and things that use them like Object.getOwnPropertyKeys), but it didn't define that for-in would follow that order; ES2020 did, though. (Details in this other answer.)

    The only real use cases for for-in on an array are:

    • It's a sparse arrays with massive gaps in it, or
    • You're using non-element properties and you want to include them in the loop

    Looking only at that first example: You can use for-in to visit those sparse array elements if you use appropriate safeguards:

    // 'a' is a sparse array
    var key;
    var a = [];
    a[0] = "a";
    a[10] = "b";
    a[10000] = "c";
    for (key in a) {
        if (a.hasOwnProperty(key)  &&        // These checks are
            /^0$|^[1-9]\d*$/.test(key) &&    // explained
            key <= 4294967294                // below
            ) {
            console.log(a[key]);
        }
    }
    

    Note the three checks:

    1. That the object has its own property by that name (not one it inherits from its prototype), and
    2. That the key is all decimal digits (e.g., normal string form, not scientific notation), and
    3. That the key's value when coerced to a number is <= 2^32 - 2 (which is 4,294,967,294). Where does that number come from? It's part of the definition of an array index in the specification. Other numbers (non-integers, negative numbers, numbers greater than 2^32 - 2) are not array indexes. The reason it's 2^32 - 2 is that that makes the greatest index value one lower than 2^32 - 1, which is the maximum value an array's length can have. (E.g., an array's length fits in a 32-bit unsigned integer.) (Props to RobG for pointing out in a comment on my blog post that my previous test wasn't quite right.)

    You wouldn't do that in inline code, of course. You'd write a utility function. Perhaps:

    4. Use for-of (use an iterator implicitly) (ES2015+)

    ES2015 added iterators to JavaScript. The easiest way to use iterators is the new for-of statement. It looks like this:

    const a = ["a", "b", "c"];
    for (const val of a) {
        console.log(val);
    }
    

    Under the covers, that gets an iterator from the array and loops through it, getting the values from it. This doesn't have the issue that using for-in has, because it uses an iterator defined by the object (the array), and arrays define that their iterators iterate through their entries (not their properties). Unlike for-in in ES5, the order in which the entries are visited is the numeric order of their indexes.

    5. Use an iterator explicitly (ES2015+)

    Sometimes, you might want to use an iterator explicitly. You can do that, too, although it's a lot clunkier than for-of. It looks like this:

    const a = ["a", "b", "c"];
    const it = a.values();
    let entry;
    while (!(entry = it.next()).done) {
        console.log(entry.value);
    }
    

    The iterator is an object matching the Iterator definition in the specification. Its next method returns a new result object each time you call it. The result object has a property, done, telling us whether it's done, and a property value with the value for that iteration. (done is optional if it would be false, value is optional if it would be undefined.)

    The meaning of value varies depending on the iterator; arrays support (at least) three functions that return iterators:

    • values(): This is the one I used above. It returns an iterator where each value is the array entry for that iteration ("a", "b", and "c" in the example earlier).
    • keys(): Returns an iterator where each value is the key for that iteration (so for our a above, that would be "0", then "1", then "2").
    • entries(): Returns an iterator where each value is an array in the form [key, value] for that iteration.

    Ref: https://bit.ly/3esbfwc