How well do you know JavaScript?

Kaylin Khanal
The Startup
Published in
10 min readMay 8, 2020

--

In this tech industry, Javascript is omnipresent. Even if it has a brand name of React or Angular or Vue, it’s still javascript under the hood with the same fundamentals.

There is no point in getting a head start to dive into these fancy frameworks without understanding the pillars of the Javascript. It is irresponsible of you to write a JS code and not understand the critical aspect of the language. This article lets you know your JS foundations as a JavaScript developer. I want you to give yourself a point for every question you answer correctly. In the end, sum all of your points and compare them with mine ;)

You will witness three major JS foundations as follows:

Types

Scopes

Objects

First and foremost, let me begin with this cliche phrase every JS developer encounter:

“In JavaScript, everything is an object.”

Q1) Is this statement correct?

Have your opinion on it. I will answer it in the end. Let’s go!

TYPES

We all know about some of the popular types such as undefined, string, number, boolean, objects, and symbols.

Q2) Can you categorize the following as types?

  • undeclared
  • null
  • bigInt
  • function
  • array

Among the five, functions and arrays are object-types. Others might have objects like behaviors but aren’t objects. In JavaScript, variables don’t have types, the values do. So, the first three items in the lists are the value types. If you had guessed all of them being types, you were right.

Q3) What’s the difference between undefined and undeclared and uninitialized?

Even an experienced JS developer might think these as synonyms. However, they are different. Undeclared means that there is no variable created in any of its scopes. Undefined means that there is no value assigned to an existing variable. Uninitialized, also known as Temporal Dead Zone (ES6), means that the variable exists without ever being initialized or variable that’s been initialized but undefined or even a variable neither created nor declared.

Q4) Does line 2 output true or false.

var myRollNo = Number(“n/a”)myRollNo === myRollNo

First of all, myRollNo value will be not a number(NaN) and NaNs aren’t equal to each other. NaNs are the only values in JS having no identity property and aren’t equal to each other. If you guessed the output as false, you are right.

If we use a utility isNaN, we will get myRollNo as true.

isNaN(myRollNo) //true

Q5) Now what about the following line of code?

Number.isNaN(myRollNo)

When I encountered this snippet, I thought it’s 100% false as NaNs are not a number. However, isNaN curbs values to numbers before it checks if it is NaN. Hence, the output is always true. So, type of a NaN is always a number, an “invalid number”.

Q6) What is Negative Zero in javascript?

In JS, signed zero(+0) are same as unsigned zero(0). However, -0 has a different value.

There was no way to find if the zero holds a negative value or not until ES6. For example,

var number= -0;number === -0; //truenumber === 0; //truenumber> 0; //falsenumber< 0; //false

You might find the output quite abstruse. The only way to understand a negative zero is by using ES6 utility called Object.is.

Object.is(number, -0) //trueObject.is(number, 0) //false

Now, you might think that you have wasted your time learning about negative zero which you will never use in your life. However, if you try to calculate mathematical limit calculation programmatically or implement object directions in games, you will find this concept helpful. If anyone of you is thinking of using Math.sign to determine the sign of zero, it won’t work for zeros. I thought the same :D

Q7) Let’s discuss coercion. Guess the following outputs:

5* “5”false+falsetrue+true2 * [1,3]4 + [5,6]

Most of the time we might be using type coercion is with null. Other than that, people often consider type coercion as one of the worst parts of JS. The code snippets above only represent implicit coercion or type conversions done under the hood. The output of the above snippets are as follows:

5* “5” //25false+false //0true+true //22 * [1,3] //NaN4 + [5,6] //’45,6'

Number(), String(), Boolean() are some of the explicit type coercion that we might be familiar with. The main point is that your code has always been using coercion even without your knowledge.

Let’s look at some of these coercion corner cases in JavaScript:

Number([undefined]); //0Number({}); //NaNString(-0); //”0"String([undefined]); //””And the strangest one was:Boolean( new Boolean(false)); //true

Q8) Guess the output of the following snippets:

1< 2< 33> 2 > 1

If you guessed both the answer will result as true in JS, you are right in the wrong way. You are correct mathematically but JS outputs the first line of code as true and the second part as “false”.

What is happening?

The Booleans are getting coerced into strings. Js evaluates 1<2 as true and then evaluates (true)< 3. Since we have non-numeric used with the less-than operator, it will coerce into a number where true represents 1. Hence, as 1 is less than 3, the output is accidentally resulted as true. However, the same “accident” won’t happen in line 2 of the snippet 3>2>1, as it will ultimately result as (true)>1 or 1>1 which is false.

However, these aren’t the coercion issues people regularly encounter in their program. The major coercion problem lies in the equality checking. Coercion is probably the main reason why people avoid “==” and opt to use “===” all the time.

Q9) Do you understand the exact difference between “==” and “===”?

== checks value(lose)

=== checks value and type(strict)

In the cases where the types are already matched, both equalities are the same. In triple equals case, they will return false in the first place if the comparing types are different.

A JS expert will always create a function which only takes particular data types as required and will know about the corner cases beforehand that he can face later on.

Q10) Will both the block execute?

var candy =[]//block1if(candy){console.log(“I am true”)}//block2if(candy==true){console.log(“I am true”)}

It’s intuitive for us to think that the blocks are the same. However, only block 1 will execute.

In block 2, candy == true will undergo type conversion and become ‘’ == true which represents 0===1, which is the reason why it won’t execute.

Similarly, if block 2 was changed as follows:

if(candy==false){console.log(“I am true”)}

It will get executed as ‘’== false coerces as 0 === 0, and the block will execute.

These are the corner cases that we must understand in JS. A simple way to deal with these corner cases is by using Boolean in the first place. eg:

if(Boolean(candy)){if (true){//Yes}}

So, here are some tips to avoid these corner cases:

  1. Avoid double equals when either side is zero, empty strings, or white case. Simply, do not use “==” when you don’t know the types.
  2. Avoid double equals with non-primitives.
  3. Don’t use double equals with true or false: allow ToBoolean or use ===
  4. Making types known leads to better code. If types are known, == is best. Otherwise, use ===.

Most of the time, we might see people willing to jump to typescript from javascript because of them not able to differentiate types. They might think that static typing will be a better option for them. Of course, Typescript has the following major benefits:

Catch type-related mistakes

Communicate type intent

Provide better IDE feedback

No programmer can indeed know or expect entire data types in each segment in the program. But, the best practice is always to be able to refractor so that we can know the types.

SCOPES

Scopes are pretty easy to grasp. Scopes are determined during code compilation, a model called “lexical scope” created during the parsing/ lexing phase of javascript. Let’s begin with a question:

Q11) Guess the output:

var hell=”hello”function check(){var hell=”not hello”console.log(hell)}check();

You must have guessed the output to be “not hello”. However, I am so sorry to tell you that you aren’t wrong :D Haha you’re right. You just need to figure out if the identifier is referenced in the local or global scope.

Q12) What about the output of the following snippets?

//note: uses strict modevar hell=”hello”function check(){hell=”not hello”goal =”Mount Everest”}check();hell;goal;

The output will be as follows:

‘not hello’‘Mount Everest’

Q13) What about the output of this snippet?

var messi=”goal”function check(){var messi= “not goal”function penalty(outcome){console.log(messi,outcome)}penalty(“Did he miss?”);}check();penalty(“Did he miss?”);

Line 5 will give you output as follows:

‘not goal’ ‘What happened’

If you got a reference error in line no 13, that’s exactly what you are supposed to. It’s because the global scope has never heard of the identifier called “penalty” which results in the reference error.

Q14) Guess the output.

for (var i=0; i<=3; i++){setTimeout(function(){console.log(`hello, you can slap me ${i} times`)},i*20)}

The output will be as follows:

hello, you can slap me 4 timeshello, you can slap me 4 timeshello, you can slap me 4 timeshello, you can slap me 4 times

We might expect the value of ‘i’ to increment in every iteration. However, there is a single variable ‘i’ but three different functions and at the end of the loop, it gets nothing but a value of 4. To use the same name for a different variable, we must create a new scope. With ES6, we can solve this with a block-scoped declaration by assigning a new value to the existing variable in that scope as follows:

for (var i=0; i<=3; i++){setTimeout(function(){let k=iconsole.log(`hello, you can slap me ${k} times`)},k*20)}

With ES6, we don’t even need to do it in this way. Using let inside the for loop will solve this problem as follows:

for (let i=0; i<=3; i++){setTimeout(function(){console.log(`hello, you can slap me ${i} times`)},i*20)}

To understand closures and modules, we must have a good concept of scopes. Advanced programmers always group their code into modules. The Module pattern is used to imitate the idea of classes so that we can store public/private methods and variables inside a single object — similar to class usage in languages like Python.

I found Adequately Good by Ben Cherry a great resource to learn about modules.

OBJECTS

To understand the use of objects, all we need is to understand the following:

  • this
  • prototypes
  • classes
  • inheritance (Object Oriented)

‘this’ keyword is quite difficult to define even for a JS developer. It’s a powerful part inside a function that references the execution context for that call which is determined by how the function is being called. In a nutshell, these are the important details you need to understand about this keyword:

If a function is called with the new keyword, ‘this’ will be the resulting object

var ozil = new String(“best”);

Here, ‘this’ will be the resulting object — ozil.

Note: We must understand what the new keyword does. It does four main things:

  1. Creates a brand new empty object
  2. It links that object to another object
  3. Calls function with this set to the new object
  4. If a function doesn’t return an object, the new keyword assumes that it needs to return ‘this’.

If a function is called with .call(), .apply() or .bind(), this will be the object that is passed in

var ozil = function () {console.log(this.assistCount)}var obj = {assistCount: ‘500’}ozil.call(obj);

If a function is called on an object, ‘this’ will be the object it was called on

var obj = {name: ‘ozil’,playerName: function () {console.log(‘his name is’, this.name)}}obj.playerName()

If a function is called on its own, this will be either undefined (if in strict mode) or the global object (if in non-strict mode)

var messi = ‘freekick king’var whoIsKing = function () {console.log(this.messi)}whoIsKing()

Now let’s discuss a bit about classes and prototypes. A class is like a blueprint or a description of the object to be created whereas a prototype is a working object instance. A “constructor call” makes an object linked to its prototype. In modern programming, we would seldom use a prototypal code as we will certainly use the class syntax and make classes. However, to understand how the class works with all its linkages under the hood, understanding the prototypal code helps a lot.

Have a look at the snippet below:

function ScoreGoal(player){this.player = player;}ScoreGoal.prototype.attribute = function(typeOfGoal){console.log(this.player, typeOfGoal);}var acrobatic = new ScoreGoal(“Overhead Kick”);var tapin = new ScoreGoal(“A Simple placing”);acrobatic.constructor === ScoreGoal;acrobatic.__proto__ === ScoreGoal.prototype;acrobatic.attribute(“is scored by ronaldo”);tapin.attribute(“by muller makes it 3–0”);

Line 1, under the hood, creates an object called prototype and we can refer to this object as ScoreGoal.prototype like in line 4.

All functions (except for arrow functions) have a .prototype property on them. We already discussed earlier the new operator and we are well aware of what happens in line 7.

Q15) How are we able to call the attribute method to the acrobatic object on line 9 when it has no such attribute method?

It’s due to the internal linkage resulted from the prototype chain. To learn in-depth about the prototypal chain, you can learn from this cool article.

Q16) There is no constructor property on acrobatic. Why does it result in true?

The reason is similar to the previous one. It does not find any constructor property on that object but goes from acrobatic all the way up to ScoreGoal.property which has constructor property pointing at ScoreGoal object.

So, we learned that we could carry out inheritance either via class or by the prototype. The major differences between both of the ways are the following:

Class Inheritance: instances inherit from classes and create sub-class relationships. Class inheritance may or may not use the `class` keyword from ES6. Instances are instantiated via constructor functions with the `new` keyword.

Prototypal Inheritance: instances inherit directly from other objects. Instances may be composed of many different objects and are typically instantiated via factory functions or with Object.create(). In JS, prototypal inheritance is considered better and simpler than class inheritance.

Thanks for your precious time. I remember that I haven’t answered the first question. The answer is no, A BIG NO! Appearing to behave like an object doesn’t make everything an object. JavaScript has features like object-wrapping and autoboxing which causes even the primitives to behave like an object.

I hope you enjoyed this game of code snippets. I got around 50% of the answers correct when I first encountered them. If you got more than that, you won haha :D Happy coding people.

Books I have been reading:

  • JavaScript: The Good Parts by Douglas Crockford
  • You don’t know JS by Kyle Simpson

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” — Martin Fowler

--

--

Kaylin Khanal
The Startup

JavaScript developer. I write mainly about react/rn/node and other js stacks.