DEV Community

Mian Azan
Mian Azan

Posted on

10 Things Beginners Must Know About Java Script

There's no denying that JavaScript is a must-have for any web developer. Gone are the days when all you needed was a little CSS and HTML to get by. Fortunately, it has so few rules that getting started is a breeze:

alert("Hello World."); // Shows the user "Hello World." in a dialog
Enter fullscreen mode Exit fullscreen mode

That concludes our discussion. With just a few lines of code, you can achieve a lot of easy things. Importing packages and declaring namespaces are not required. You write a piece of code, and it executes. However, the lack of structure that allows JavaScript to have such a low barrier to entry also allows beginners to write unstructured, brittle code without even recognising it. This unstructured code will come back to bother you as an application expands, in the form of unforeseen, difficult-to-find defects.
In this article, I'll address some of the most common misunderstandings and errors that create misery for new JavaScript developers. Here are a few things that any new JavaScript developer should be aware of:

1. You can add properties to almost everything

JavaScript has only three primitive data types: String, Number, and Boolean. Everything else (if it’s not null or undefined) can have properties added to it.
Note: Even though String is a primitive type ("hi"), there is another incarnation of String in JavaScript which is an object (new String("hi")).

var a = {}; // create a new object 
a.b = 'hello';
Enter fullscreen mode Exit fullscreen mode

In the above code, a.b meant nothing until I set a value to it. Now a has a property called b. But wait, it gets weirder.

var a = []; // create an array 
a.b = 'hello';
Enter fullscreen mode Exit fullscreen mode

Great, so now you’ve got an empty array, with a property on it called b.
Caution: Just because you can put properties on arrays doesn’t mean you should. As I’ll discuss later, the above code will change the behavior of for...in loops on that array.
How about this?

var a = function() {}; 
a.b = 'hello';
Enter fullscreen mode Exit fullscreen mode

Yes, that’s right. a is now a function, with a property. Which brings me to my next point.

2. Functions are objects

Treating functions as values is becoming increasingly common in more languages, although depending on your background, you may not be aware of this.

function doIfTrue(isTrue, whatToDo)
{
  if(isTrue)
    whatToDo();
}
doIfTrue(true, function() {alert('hello');}); //  alerts "world"
doIfTrue(false, function() {alert('world');}); // does nothing
Enter fullscreen mode Exit fullscreen mode

The function above treats the whatToDo parameter as a function.This pattern enables developers to do some quite powerful things, such as putting up event handlers with very minimal code.

3. for...in loops iterate over property names, not values

Developers who have worked with Java or C# are familiar with "foreach" loops, which run through all the values in a collection. There isn't a similar loop in JavaScript (yet). A "for in" loop, which is the closest thing, has a few key differences:

var arr = ['a', 'b', 'c']; 
for(var i in arr) { 
  alert(i); // 0, 1, 2 
  alert(arr[i]); // 'a', 'b', 'c' 
}
Enter fullscreen mode Exit fullscreen mode

As you see, the variable used by the for...in loop gives you the keys by which other values can be created, but you have to perform the extra step of getting the values off of the real object.
Why does JavaScript do this? The main cause is that for...in was not made for arrays: it was made for objects that have properties on them:

var pairs = {'a': 'apple', 'b': 'banana'};
for(var key in pairs) {
  alert(key);        // 'a', 'b'
  alert(pairs[key]); // 'apple', 'banana'
}
Enter fullscreen mode Exit fullscreen mode

Caution: Because a for...in loop iterates over the properties on an object, you’ll get odd behavior if you use the loop on an array that has extra properties added to it, For this reason, you should avoid using for...in loops on arrays–use simple for loops instead. They’re faster anyway.
Note: ECMAScript 6 will introduce for...of loops, which iterate directly over values.

4. Understand how .prototype works

JavaScript uses a special prototype property to answer the problems that other languages use classes to solve. Consider the following:

function Person(first, last)
{
  this.first = first;
  this.last = last;
}
var john = new Person("John", "Doe");
var mary = new Person("Mary", "Deer");
Person.prototype.full = function() {return this.first + " " + this.last;};
alert(john.full());
Enter fullscreen mode Exit fullscreen mode

There are a lot of things happening here.

  1. We create a function, which will set properties on its this object when called.

  2. We create two separate instances of that function by putting the new keyword before our function calls. This ensures that john and mary refer to completely separate objects, each with their own first and last properties.

  3. We create a new function and assign it to the full property on our Person function’s prototype property. The prototype property exists on all functions, and allows you to define fall-back properties that should exist on every object created from that function.

  4. We call the full() function on john. JavaScript sees that the john object doesn’t actually have a full function on it, so it looks for a Person.prototype.full() function and calls that instead. Within that call, however, this still refers to the john object.

5. Variable scoping

Global variables should be avoided by all developers, regardless of language. In Javascript, though, it's easy to do by accident because no one forces you to structure your code into modules.

var message = "hello world"; 
alert(message);
Enter fullscreen mode Exit fullscreen mode

If the above code is run all by itself in the browser, it will create a new global property on the window object, called message. That means that if any other code on your site also has a similarly-declared variable called message, they’ll stomp on each other.
In Javascript, all variables declared with the var keyword are scoped to their declaring function. That means if you want to make sure your variables aren’t global, you should put them in a function, and then call that function.

(function() { 
  var message = "hello world"; 
  alert(message); 
})();
Enter fullscreen mode Exit fullscreen mode

Developers with a background in other languages based on C syntax are used to variables scoped by curly braces ({}). In JavaScript, variables declared with var are “hoisted” to the top of the function they’re declared in. This code:

function sayHi() { 
  if(true) { 
    var s = "hi"; 
  } 
  alert(s); // alert("hi") -- `s` is still within scope. }
Enter fullscreen mode Exit fullscreen mode

… is the same as this:

function sayHi() { 
  var s; 
  if(true) { 
    s = "hi"; 
  } 
  alert(s); 
}
Enter fullscreen mode Exit fullscreen mode

This also means that if you refer to a variable outside the scope of your function, you’ll use the value of that variable at the moment the code is run, not at the moment your function is created. This trips up beginners all the time:

var thingsToDo = [];
 for(var i = 0; i < 2; i++) {
   thingsToDo.push(function() {alert('hello ' + i);}); 
 }
 for(var k in thingsToDo) {
   thingsToDo[k]();               // alerts "hello 2" twice.
 }
Enter fullscreen mode Exit fullscreen mode

Remember that the variable i starts as a 0 value, but by the time it’s called (in the second loop) its value has been incremented to 2. To capture the value of i when you create the function, you have to create another function scope:

var thingsToDo = [];
function createHelloAlert(v) {
  // `v` only exists within this method call.
  return function() {alert('hello ' + v;} 
}
for(var i = 0; i < 2; i++) {
  thingsToDo.push(createHelloAlert(i)); 
}
for(var k in thingsToDo) {
  thingsToDo[k]();  // alerts "hello 0", then "hello 1".
}
Enter fullscreen mode Exit fullscreen mode

The let keyword will be introduced in ECMAScript 6, allowing you to declare a variable that is scoped to the curly-braces. Lexical scoping is the term for this.

6. Variables that aren’t explicitly declared can be global

Let's say you remember to encapsulate your code in a function, but you don't remember to include the var keyword:

(function() { 
  message = "hello world"; 
  alert(message); 
})();
Enter fullscreen mode Exit fullscreen mode

When you set a variable’s value, and you haven’t declared it to be a variable for the current function scope via the var keyword, JavaScript assumes you mean this.propertyName. So the above code is the same as this:

(function() { 
  this.message = "hello world"; 
  alert(this.message); 
})();
Enter fullscreen mode Exit fullscreen mode

If you’re a Java developer, you’re saying to yourself, “What’s this? No, really. What is this?” In other languages, this means the instance of the class that you’re looking at, but in JavaScript it means the object that your function got called on. If you’d done this:

var a = {
  foo: function() {
    this.message = "hello world";
  }
};
a.foo(); // `a.foo()` means foo's `this` is `a`.
alert(a.message); // outputs "hello world"
Enter fullscreen mode Exit fullscreen mode

… then calling the foo method puts a value on a‘s message property. But since our original code snippet is calling a function that doesn’t have anything in front of it, this is given a fallback value of window. You end up creating another global variable just by forgetting the var keyword.

7. JavaScript never sleep()s

Threads are a concept in many programming languages that allows you to perform many operations at the same time. The issue is that multi-threading throws up a big can of worms, including thread locks and other race situations that even the most experienced programmers have trouble dealing with.
JavaScript avoids these issues entirely by only allowing one piece of code to run at a time. This is great, but it requires us to write our code in a different way. Most languages create a layer of abstraction over operations where the program is waiting for something to happen. For example, in Java, you can call Thread.sleep(100), and the rest of your procedure won’t run until 100 milliseconds have passed.
When you just have one thread to work with, you can't afford to leave it idle for hundreds of milliseconds at a time–the UI will freeze and the user experience will suffer. As a result, JavaScript practically never causes a halt in operation. Instead, asynchronous callbacks are used to specify what should happen after an operation completes. Consider the following scenario:

window.setTimeout(function() { console.log(a); }, 1000); 
console.log('hello world'); 
var a = 'got here';
Enter fullscreen mode Exit fullscreen mode

The above code will first create a “hello world” message (even though that line of code comes after the setTimeout() method), and then print “got here” one second later. Even if we changed the timeout to 0, we know that the a variable will be initialized before getting logged because no other JavaScript can run until this code has finished.
Beginners will often write code like this, and then wonder why a doesn’t have a value:

var a; 
$.ajax(url, {success: function(e, data) { a = data; }); console.log(a); // BAD! This line will run before `a` gets set to a value!
Enter fullscreen mode Exit fullscreen mode

Don’t fall into that trap.
There are a few caveats that I should mention.

  1. Not all functions that you pass into other functions are asynchronous callbacks. The following code works just fine, because doIfTrue() calls its whatToDo argument, synchronously, before it returns:
var a = 'hello'; 
doIfTrue(true, function() {a = 'world';}); 
console.log(a); // prints "world"
Enter fullscreen mode Exit fullscreen mode
  1. alert() is one of very few exceptions to the no-blocking rule–nothing happens until the alert window closes. Even the timeouts freeze! This is one reason that it’s usually best to avoid using alert().

  2. Web Workers can allow you to run CPU-intensive tasks on a separate thread, but they’re structured very carefully to avoid race conditions. Beginning developers rarely need to worry about such things.

8. Automatic type conversions

Like many languages JavaScript does some automatic conversions between types under certain circumstances. For example:

var s = 1 + ""; // yields "1"
Enter fullscreen mode Exit fullscreen mode

JavaScript takes this a little further than many languages, though, and you can leverage this fact to make your code very concise. For example, instead of if(a != null) {...}, you can just say if(a) {...}. Even though a isn’t a Boolean, JavaScript can tell you want to treat it like one, so it determines whether a‘s value is “truthy” or “falsy” and acted accordingly.

Falsy JavaScript values include:

  • false
  • 0
  • empty strings ('' or "")
  • null
  • undefined
  • NaN Everything else is Truthy.

Here’s another example:

var a = b || c;
Enter fullscreen mode Exit fullscreen mode

If b has a truthy value like “Bob”, that’s the value that a will get. If b is falsy, a will get the value of c.

You can force a truthy/falsy value to become a true/false value by negating it twice:

var trueOrFalse = !!value;
Enter fullscreen mode Exit fullscreen mode

Also, in equality comparison, x == y has some complex rules for converting different value types. This can yield weird behavior, like:

var a = "1" == true; // true: "1" -> 1, which is truthy
Enter fullscreen mode Exit fullscreen mode

And you can use the === operator for strict comparison without automatic conversion.
var a = "1" === true; // false: different-typed values are not equal.

9. JavaScript is code – not data or markup

For simplicity, many online tutorials will mix JavaScript and HTML, like so:
Mixed HTML and JavaScript (bad)

<button onclick="return confirm('Delete this object?');">Delete</button>
Enter fullscreen mode Exit fullscreen mode

This works fine for small tutorials, but it has some serious drawbacks when you’re writing real applications. It mixes the programmatic behavior of the UI elements (represented by JavaScript) into the structure and data that is (represented by HTML). HTML should not be deciding how it interacts with the JavaScript. Instead, separate your JavaScript code from the HTML, and let it decide how it interacts with the page.

<button data-confirmation="Delete this object?">Delete</button>
Enter fullscreen mode Exit fullscreen mode

JavaScript (with jQuery)

// Set a click handler for anything with a data-confirmation attribute. 
$('[data-confirmation]').click(function() { 
  var message = $(this).data('confirmation'); 
  return confirm(message); 
});
Enter fullscreen mode Exit fullscreen mode

As you can see, the JavaScript has now defined the behavior for any element with a confirmation data attribute. This approach, sometimes called “unobtrusive JavaScript,” has several advantages, including:

  1. It usually makes HTML code more concise and readable.
  2. It allows you to declare a UI concept in one place and reuse it throughout your system.
  3. If you decide to change your implementation details (e.g. “browser confirmation dialogs are ugly and inconsistent–we want to use a popup instead!”), you can do this in one place without touching your HTML. If you're using Angular or Polymer to render templates in the browser, this separation implies placing HTML in one section of your project and JavaScript in another. If you're using a server-side engine like JSP or Razor, you should keep your JavaScript code separate from your dynamically created HTML tags in static, cached.js files.

10. JavaScript is not just for browsers

Since its inception in 1995 (allegedly in ten days), JavaScript has gone a long way. Now, technologies like node.js allow JavaScript to be run outside of any browser. The following are some examples of how JavaScript can be used as a general scripting language:

  1. JavaScript is used to write server-side code. Ghost.org is an example of a web application with JavaScript server-side programming running on node.js.
  2. Building LESS files into CSS. Less.js is a JavaScript-based LESS converter that is the fastest and most accurate on the market. It's a good idea to pre-build the CSS by executing the lessc compiler via node.js if you're using LESS and don't want it to be re-translated client-side on every page view.
  3. Organizing and managing construction projects. What if you wanted to run unit tests on your JavaScript every time you made a change to ensure you didn't break anything? Grunt.js can help with that, thanks to its watch and Karma plugins. Alternatively, you can tell Grunt to rebuild all those CSS files whenever you make a modification to an LESS file. If you want to create web applications, you'll need to understand JavaScript. You might as well apply that expertise to other elements of your application too!

Final Thoughts

JavaScript is here to stay, whether you like it or not. It is currently the de-facto language for creating any type of web-based rich user experience.
JavaScript is a sophisticated language with many complexities and nuances. The more you study about JavaScript, the more you realise just how little you know. However, armed yourself with information will help you avoid costly mistakes that new developers frequently make.
Good Luck.😅

Top comments (0)