Three JavaScript Quirks That Java/C Developers Should Know

Originally published at: http://www.sitepoint.com/three-javascript-quirks-java-c-developers-should-know/
JavaScript can be a deceiving language and it can be a real pain because it isn’t 100% consistent. As it’s well known it does have bad parts, confusing or redundant features that should be avoided: the infamous with statement, implicit global variables and comparison erratic behavior are probably the best known.

JavaScript is one of the most successful flames generator in history! Besides the flaws it has (which are, in part, addressed in the new ECMAScript specifications), most programmers hate JavaScript for 2 reasons:

  • The DOM, which they erroneously think is equivalent to the JavaScript language, which has quite a terrible API.
  • They come to JavaScript from languages like C and Java. They are fooled by JavaScript’s syntax into believing that it works the same way as those imperative languages do. This misconception will lead to confusion, frustration, and bugs.

That’s why, generally, JavaScript has a worse reputation than it deserves.

During my career, I noticed a few patterns: language features most developers with a Java or C/C++ background assume to be identical in JavaScript, while they are completely different.

This article gathers the most troublesome ones, comparing the Java-way to the JavaScript-way to shown differences and highlight best practices in JavaScript.

Scoping

Most developers start working on JavaScript because they are forced, and almost every of them start writing code before taking a moment to learn the language. Every such developer has been tricked by JavaScript scope at least once.

Because JavaScript’s syntax closely resembles (on purpose) C-family languages, with curly braces delimiting function‘s, if‘s and for‘s bodies, one would reasonably expect lexical block-level scope. Unfortunately, this is not the case.

First, in JavaScript variable scope is determined by functions, not by brackets. In other words, if and for bodies don’t create a new scope, and a variable declared inside their bodies is actually hoisted, i.e. created at the beginning of the innermost function in which it is declared, or of the global scope otherwise.

Second, the presence of the with statement forces JavaScript scoping to be dynamic, impossible to determine until runtime. You might not be surprised to hear that the use of the with statement is deprecated: JavaScript stripped of with would actually be a lexically scoped language, i.e. the scope could be completely determined by looking at the code.
Continue reading this article on SitePoint

2 Likes
function myFunction() {
   console.log(i);
   var i = 0;
   console.log(i);
   if (false) {
      var i = 5;
      console.log(i);
   }
   console.log(i);
}

Why you got

undefined
0
5
5 

???

#Just another JS article
Congratulations, You have just added another article to the interwebz that shows how mis-understood JavaScript is. Not because you showcase any knowledge at all ofcourse. Your examples are wrong (did you even bother checking them?) and I think you didn’t even take the time to look up anything at all about the language.

##A bad start:

Your first example is wrong. It does not output ‘undefined, 0 5 5’. It does however output ’ undefined 0 0’. This because thx to hoisting the proper equivalent is this:

function myFunction() { 
  var i = undefined; //the compiler is smart enough to know we don't need to define i twice
  console.log(i);  //undefined
  i = 0; //simple assignment
  console.log(i); // 0
  if (false) { //the following if block is never executed
    i = 5;
    console.log(i);
  } 
  console.log(i); //0 since id did not change
}

##Prototype, functional, potatoe, potato, whatever
You state that JavaScript is a functional language, kind of. Not really, it looks like one. So lets call it one. Or whatever… Why force it to be anything else than what is really is? Why even try. It’s a prototype based language, and that is really powerful!

You also state a few lines later that function is a primitive. But it’s also an object. These two statements do not go well together. A quick fact checking on mdn would give us the following primitives:

  • string
  • number
  • Boolean
  • null
  • undefined

The mdn article also talks about primitive Wrappers. Objects that wrap around a primitive. This explains the behavior:

typeof new Number(5); //Object
typeof 5; //number

##Strange use of language
Normally, in computer science, we use words like ‘is a’. You don’t, you say

Function, the type of functions, is built upon Object

Not sure what you mean here, simply put. A Function is an Object. This because it is not a primitive. You then go on to ‘prove’ this by doing a typeof function.prototype . Not sure what your point here is. You have proven that the prototype is an object. Wow.

You also state that functions (can) have properties. Not sure if this is such a special thing, it’s an object…

And to explain closures, the following sentence does that really well: (taken from crockfords website)

An inner function always has access to the vars and parameters
of its outer function, even after the outer function has returned.

##Examples should explain
You end the article with some examples, not sure what they should prove. Your Person function is a factory-like function that returns an object that has access to a passed in variable ‘thanks to’ scope, closure, whatever. This doesn’t make the variable private, It just makes the variable a memory-leak. The variable also has nothing to do with the object. The object consists simply of 2 functions that have access to a non-local variable. Your point? Personally, if you want to show how to create an object with private vars, use privileged functions:

function Person(name) {
  var privateName = name; //don't touch me
  
  //define privileged functions:
  this.getName = function() {
    return privateName;
  }

  this.setName = function(name) {
    privateName = name;
  } 
}

var myPerson = new Person('foo'); //using new is so much cooler
myPerson.getName(); //foo
myPerson.privateName; //undefined

For people who would like to have a good read on scope and stuff: crockford

EDIT: I just can’t resist. You talk about JS being the first ‘mainstream’ language to implement closures. this shows that you or, have no idea what closures are, or with mainstream, you mean: ‘that I know’. The fist language implementing closures was somewhere around 1970 (if I remember correct). I wasn’t even born then…

Kind regards,
A sad reader

3 Likes

I did not understand this one as well. I can’t get the same output even when using "use strict";

Unfortunately there is a typo,
if (false) was supposed to be if (true)
Apologies!

Hi,
thanks for your valuable and polite feedback.

You are right about the first example, there is a typo: if (false) was supposed to be if (true) on line 6.
Although you are also right it is not acceptable, unfortunately typos and errors happens.
Thanks for catching it and adding a walkthrough through the function, that I’m sure will help readers.

About your last example, using that syntax (creating an object with a constructor) is a perfectly valid alternative.
Your example, however, is error prone, because if Person is called without new in front of it, undefined will be returned - which is the main turn off for constructors.
This is easily solved, though:

function Person(name) {
  if (!(this instanceof Person)) {
    return new Person(name);
  }
  
  //define privileged functions:
  this.getName = function() {
    return name;
  }

  this.setName = function(newName) {
    name = newName;
  } 
}

var myPerson = Person('foo'); //now works even without new

By the way, you don’t really need to declare another privateName var, since you can just use the argument to the constructor, which will as well captured in the get and set functions’ closures.

I think you are making a bit of confused about the term “mainstream”.
I never claimed that JavaScript invented closures, but you can hardly say that Scheme was ever a mainstream language, while JavaScript is the first language having closures that is widely adopted.
But you don’t have to take my word on that, you seems to have enough confidence in Douglas Crockford to take his (browse a bit through his videos, will you?, and you’ll find those exact same words).

Speaking of Crockford, thanks for the extra pointers, they will certainly be a wonderful reading/listening that I strongly suggest to every one.

Have a very nice day

This has been fixed. Thanks for pointing that out.

Makes sense, thanks!

My example is not error-prone. You just don’t understand functions.

this is not personal, if you feel it is a personal rant, it is not. It is just a frustrated dude who thinks he is the next #worldDominator vomiting words into a textbox.

I should advice everyone to look up your blog (I think it is yours) and read up on the really strong articles you have (I really mean this. I really like the topics you are addressing there and they are really well explained).

I think it is also safe to say that the examples you are using in this article are bad… They do to much, using type-coercion in an example of hoisting simply adds to the confusion. That same example in fact demonstrates that hoisting really is: moving a var statement to the top of the function block. You should emphasize that.

I am also not at all convinced of your JS-knowledge, but it is hard to say something about that from one article - or comment.

##Default return values
Functions always return a value. Always. If no return; is used, then the default value returned is undefined. If you use the new keyword, the default value returned is this.

Writing:

function Person() {};
var p = new Person();

Is the same as:

function Person() { return this; }
var p = Person();

Using your approach doesn’t really fix anything, unless developer laziness counts as a problem that should be solved with code. Even worse, it helps writing hard-to-read code. We have a keyword to help us, so let’s use it.

And no, I don’t need to declare my privateName in my example. But think of code-readability. Think of variables that are not passed in in the constructor. Think of creating a clean example that shows one thing and one thing only. My example is used to illustrate how to create private variables with public getters and setters.

##Hoisting, var, function and var function

You kind of make a point, but kind of miss the point as well when you talk about hoisting and stuff. In JavaScript all variables and function declarations are hoisted, simply put (as you correctly state) they are moved to the top of the current function block.

function foo() {
  console.log(a); //undefined
  var a = 5;
}
foo();

Is actually parsed as:

function foo() {
  var a;
  console.log(a); //undefined
  a = 5;
}
foo();//after the function exits, a is garbage collected since we no longer reference it

But what happens if we forget to declare our variable all together?

function foo() {
  console.log(a); //undefined
  a = 5;
}
foo();

This roughly translates to:

var a;
function foo() {
  console.log(a); //undefined
  a = 5;
}
foo();

Our variable a is declared globally, not because it is hoisted, but simply because we forgot to declare it, and so JavaScript declares it globally for us, the true friend he is.
And we now can no longer garbage collect our variable because it is global.

Then there is the difference between function declaration and function expression/statement. The first is hoisted, the latter not. But why is it hoisted? this has to with execution time. The JS-engine first parses our codezz and creates the execution context. This means declaring variables (and thus hosting them), parsing function declarations, … The next phase is execution. He simple walks over line by line and executes it.

//this is evaluated on execution-time
foo();

//the named function is created on parse-time, and thus hoisted
function foo() {
  console.log('foobar');
}

The following however will not work:

foo();
var foo = function foo() {console.log('foobar');}

This because it translates to:

var foo; //the declaration of our variable is hoisted
foo(); //but it is still undefined here
foo = function foo() {console.log('foobar');} //here we assign a function expression to the variable.

Our function expression is only parsed on execution-time instead of parse time. #confusion ← this hashtag exists purely for JavaScript

That is fixed by declaring “use strict”;

1 Like

Totally right about constructors and return type. Thanks for giving me the chance to talk about this a bit more.
Indeed, what I see as the very problem with new and constructors, is the peculiar behavior of

  1. The this pointer
  2. The return type
    for constructors.

You yourself, in the rush of the moment, are making a bit of confusion in your counter example:

function Person() {};
var p = new Person();   //assign a new Person object to p

has a totally different behavior from

function Person() { return this; }
var p = Person();  //assign the global object to p

Back to your example, for sake of completeness, say we use an explicit return statement (return this;), what is going to be returned when we use var p = Person('foo') (without new)?
Not a new Person, of course, nor undefined.
To let everybody else understand: since when we call a function as a function (i.e. not as a method, constructor or by using apply/call) this is set to the global object, then window (in browsers, ofc) is returned.
If we use strict mode however, this will be set to null instead, and an error will be thrown this.getName = ....

Now, on the other hand, by using that safe constructor pattern,

  if (!(this instanceof Person)) {
    return new Person(name);
  }

a Person object will be returned both in strict mode (ES5 and newer versions) and “legacy” mode, no matter if the caller uses new or forgets about it.
That’s why this pattern is safe, and the other is error prone.

Now, JavaScript allows you to do the same thing in many different ways, and one is free to like enforcing the use of constructors and new.
Personally, I think this is trying to make it more similar to Java, and in fact it astray you from the prototypical pattern in favor to something similar to the class pattern.

You are also totally free not to care about lazy programmers, and just hope they never forget to prepend new to your library’s constructors.
But I guess it is good to know you have an easy alternative to make your code more robust - personally I like that.

Again, you all don’t take have to take my word on that: Crockford himself advice against the use of constructors in his videos and his book (Javascript: the good parts - new is actually included in the bad parts), and you can check another great book, Javascript Patterns by Stefanov for the safe constructor pattern.

About lazyness in coding, great video featuring Marc Stiegler https://www.youtube.com/watch?v=eL5o4PFuxTY
Bottom line (among others) let’s make it easy (and harmless) for programmers to be lazy :smiley:

BTW, thanks for the advice, I will try to revise the examples and make them more focused and simpler.

Have a nice day!

To complete the discussion about this example, the reader should be aware that either reusing the function parameter or declaring a private var inside Person and assigning the parameter to it, in both cases this value will be kept private only if it is an immutable value (a primitive). If something is it is an object or an array (so essentially something passed by reference and not by value), it will still be possible to modify it outside of the function, because assignment only perform shallow copy.

Try this to check it:

var a = [1,2,3];
var p = Person(a);  //Person {getName: function, setName: function}
p.getName();  //[1, 2, 3]
a.push(4);
p.getName();  //[1, 2, 3, 4]

To avoid this, you need to make a deep copy of the parameter you get (to this end, declaring a privateName field, although not stricly necessary, helps for clarity and readability, agreed on that).
For instance, you could try something on the line of:

function deepcopy(x) {
  return JSON.parse(JSON.stringify(x));
}
function Person(name) {
  "use strict";
  if (!(this instanceof Person)) {
    return new Person(name);
  }
  var privateName = deepcopy(name);
  
  //define privileged functions:
  this.getName = function() {
    return privateName;
  }

  this.setName = function(name) {
    privateName = deepcopy(name);
  }
  return this; 
}

This will make a deep copy of your parameter that won’t be accessible to anyone but your privileged methods.

Many of the JavaScript built in functions/objects make use of the difference between calling them using new and calling them without.

For example:

today1 = Date();
today2 = (new Date()).toLocaleString();

the first of these is calling the Date() function to return today’s date in whatever format your browser is set to use while the second of these creates a Date() object and then uses a method on that object to return today’s date in whatever format your browser is set to use.

Similar function/object pairs exist for Boolean() Number() and String() where the function converts whatever is passed to it to the appropriate primitive data type while the object call (with new) creates an object of that type (which is not the same type as the primitive that the function returns).

Hi.

I think the article had two issue, one of which was a simple typo. Based on that, I think your reply was a bit too hard for what is, in my opinion, only one real error.

First error outlined is that the first snippet doesn’t work properly. This was because the “if (false)” was actually an “if (true)”. You seem to understand JavaScript enough to easily spot that this was just a typo. So, perhaps, instead of writing 15 lines of text claiming how bad was the code and the article, I think you could have simply written: “Hey dude, there’s a typo in your article”. It’d have been more than enough. As a long-time writer (~130 articles to date) I have made a lot of such typos because it simply happens (as the author himself replied).

Second error is more severe and I apologize for that as the reviewer. The error is: “functions are a primitive type in JavaScript.” This is of course wrong and I’ve fixed the text.

Just to make it even more clear how your comment was too hard, I want to highlight this point:

You talk about JS being the first ‘mainstream’ language to implement closures. this shows that you or, have no idea what closures are, or with mainstream, you mean: ‘that I know’. The fist language implementing closures was somewhere around 1970 (if I remember correct). I wasn’t even born then…

Keeping in mind that mainstream languages today are pretty much JavaScript, Java, PHP, C#, C/C++, and Ruby, why asserting that JS has closures and is mainstream is wrong? To me this seems absolutely true. If you consider some old fashion language from the '70 as mainstream today, it’s fine. However, I’m pretty sure that most developers would agree with that statement.

Another example of how you overreacted:

You also state that functions (can) have properties. Not sure if this is such a special thing, it’s an object…

In JS functions are object and the author is targeting people coming from Java and C. Therefore completely beginners. With this in mind, isn’t explicitly asserting that functions can have properties worth mention? I thinks so.
Moreover, few days ago I was explaining exactly this concept to a friend of mine who is a pure Java developer and it’s just approaching JavaScript. He was shocked twice. The first time when I explained to him that functions in JavaScript are objects. The second time when I highlighted that because functions are objects they can have properties. If you, thanks to your knowledge, don’t find this concepts shocking then fine. But don’t assume that other developers wouldn’t benefit from it.

So, in conclusion, thank you for the two points but I think your reply was a bit exaggerated.

Exactly, that’s a very good point.
In all those cases, though, these functions actively handle the case when you don’t call them as constructors.
Personally I think that, especially for Date, this is not the clearest design (maybe f.i. a Number.tonum method would have been as effective?) but chances that it leads to unexpected behavior are quite low indeed.

But again, very good example, right to the point.
Thanks

Good article. Thanks for the effort, just please proofread or have someone proofread before publishing. The grammatical errors and choice of wrong words takes away the reader’s focus and makes it hard to get through.
Other than that drive on!!

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.