5 things that might surprise a JavaScript beginner/ OO Developer
Tags: tutorial, webdev, javascript, beginners
Published: 2020-07-08 15:19:57

---
title: 5 things that might surprise a JavaScript beginner/ OO Developer
published: true
description: JavaScript is a bit different from an OO language. Let's talk about 5 things that may confuse a JS beginner/OO developer.
tags: tutorial, webdev, javascript, beginners
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/0m2w34ggv98642iuaubw.jpeg
---

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris

TLDR; this is not a critique against JavaScript, it's just acknowledging the fact that it differs a bit from OO languages and you can either curse JS Or you can use the patterns that are made possible through that, to your advantage.

I love the language but it works differently than other languages I'm used to.

Regardless if you are a beginner to JavaScript or beginner to programming there are things in JS that might surprise you. Just because it surprises you doesn't mean it's wrong, it's just different, quirky, or perfectly sane, depending on what your previous experience is. Each one of the upcoming topics deserves their own article or even book, *almost*, but here goes:

## -1- Really really equals

If you learned to code in some other language maybe Java, you've learned that one `=` means an assignment and `==` compares. In JavaScript, you have both `===` and `==` for comparing equality. Which one to use? What's the difference? `==` compare values only. Consider this example:

```javascript
if('2' == 2) {} // true
```

It returns `true` when it's the same value but the type differs.

Look at this example now:

```javascript
if('2' === 2) {} // false

if(2 === 2) {} // true
```

Above the `===` detects that `'2'` and `2` have different types and therefore evaluates to `false`. It's generally recommended to be using this way of doing comparison.

## -2- There are many ways to create an object

In Java or C# you have a class. From that class, you can instantiate an object. It makes sense. JavaScript gives you more options. There you can create an object in the following way:

- **Using a class**, There is the keyword `class` that you use to define fields, methods, getters/setters all within the context of a class. Here's an example:

```javascript
class Person {
  constructor(n) {
    this.name = n;
  }

  getName() { return this.name; }
}
```

- **Object literal**, You can define an object without defining a class. All you need is `{}`. It can look like so:

  ```javascript
  const person = {
    name: 'chris',
    city: 'location',
    getAll() {
      return `${this.name} ${this.city}`;
    }
  }
  ```

- **Object create**, you can use the method `Object.create()` to create an object. It takes a *prototype* object to base it off of. Here's an example:

  ```javascript
  const address = {
    city: '',
    country: ''
  } 

  const adr = Object.create(address);
  adr.city = 'London';
  adr.country = 'UK'
  console.log(adr.city); // London
  console.log(adr.country); // UK
  ``` 

### Block statements, look ma no scope

Block statements, `if`, `for`, `while` etc, don't create a local scope. That means whatever you create in there is accessible outside of the statement, like so:

```javascript
for (var i =0; i< 10; i++) {
  console.log(i);
}

console.log(i);
```

The last `console.log()` will print `10`. This might surprise you. 

> Yes, why is JS designed so that is `i` still alive?

Ask Brendan Eich, it's a feature :)

To make JS behave like other languages you might know, you need to use a `let` or a `const`, like so:

```javascript
for (let i = 0; i< 10; i++) {
  console.log(i);
}

console.log(i);
``` 

Running this code now states `i is not defined`. Why did this work? Well, `let` allows you to declare variables that are limited to the scope of a block statement. So it's the usage of the keyword `let` over `var` that does this rather than the block statement being given a scope. (Thanks to Will for this comment) 

> Phew

## -3- Context, what's the value of `this`

You might have heard the jokes that no one knows what `this` is. Starting out with an empty file `this` is the global context.  Consider the following code:

```javascript
global.name = "cross";

function someFunction() {
  console.log(this.name);
}

someFunction();
```

Above we are assigning `name` to the variable `global` (that's what we call it in Node.js, on the frontend it would be `window`). The value of `this` comes from the global context. 

Let's look at a different example below:

```javascript
var object = {
  name: 'chris',
  getName() {
    console.log(`${this.name}`);
  }
}

object.getName();
```

Here, the value of `this` is the object itself, it knows what `name` is, i.e the value `chris`.

### Changing context

We can change what `this` is. There are some helper methods in JavaScript that allows us to do that `bind()`, `call()` and `apply()`. Consider this example again but with `object` added:

```javascript
global.name = "cross";

var object = {
  name: 'chris',
  getName() {
    console.log(`${this.name}`);
  }
}

function someFunction() {
  console.log(this.name);
}

someFunction();
```

We can alter `this` from the global context to that of `object`. Below we showcase how anyone of the mentioned methods can use this principle:

```javascript
someFunction.bind(object)();
someFunction.call(object)
someFunction.apply(object)
```

It will now print `chris`, instead of `cross`.

These three methods are used in a little bit different ways normally but for this example, they are pretty equivalent.

### The `this` confusion

Ok, so when are we actually confused what the value of `this` is? It happens in more than one place, but one common place is when we try to use a constructor function to create an object like so:

```javascript
function Person(n) {
  this.name =  n || 'chris';
  function getName() {
    return this.name;
  }
  return {
   getName
  };
}

const person = new Person();
console.log(person.getName()) // undefined 
```

This is because the `this` changes for inner functions once you use `new` on it. There are different solutions to fixing this:

**Solution 1 - this = that**

A way to approach this is to make it **remember** the value of the outer `this`. Rewrite the above example to look like this:

```javascript
function Person(n) {
  this.name =  n || 'chris';
  var that = this;
  function getName() {
    return that.name;
  }
  return {
   getName
  };
}

const person = new Person();
console.log(person.getName()) // 'chris'
```

It fixes the issue by introducing the `that` variable that *remembers* the value of `this`. But there are other solutions. 

**Solution 2 - Arrow function**

```javascript
function Person() {
  this.name = 'chris';
  
  const getName = () => {
    return this.name;
  }

  return {
    getName
  }
}

const person = new Person();
console.log(person.getName()) // 'chris'
```

The above replaces the `function` keyword for an arrow function `=>`. 

**Solution 3 - Use a closure**

The third solution is to use a so-called `closure`. This involves not using the *new* keyword but relies on the fact that JavaScript barely needs to use `this`. Consider the below code:

```javascript
function Person() {
  var name = 'chris';

  const getName = () => {
    return name;
  }

  return {
    getName
  }
}

const person = Person();
console.log(person.getName()) // 'chris'
```

Above `this` has been completely removed. We are also NOT using `new`. IMO this is the most JavaScript-like pattern to use. 

**Solution 4 - put method on the prototype**

In this approach, we use a class:

```javascript
function Person() {
  this.name = 'chris';
}

Person.prototype.getName = function() {
  return this.name;
}

const person = new Person();
console.log(person.getName()) // 'chris'
```

This is a good solution for more than one reason. It solves the `this` problem but it also makes sure that the method is only created once, instead of once per instance.

**Solution 5 - use a class**

This is quite close to the fourth solution:

```javascript
class Person {
  constructor() {
    this.name = 'chris'
  }

  getName() {
    return this.name;
  }
}

const person = new Person();
console.log(person.getName()) // 'chris'
```

For this article to be crazy long I can't name all the possible cases where `this` isn't what you think it is. Hopefully, these solutions offer you an insight into when it goes wrong and approaches to fix it.

## -4- `const` works, but not the way you might think

There's the `const` keyword, we've seen how it creates a local scope. But wait, there's more :) The word `const` makes you think it will always have this value, it's **a constant**, unchanging etc. Weeell.. Looking at the following example:

```javascript
const PI = 3.14 // exactly :)
PI = 3;
```

The above gives me the error `Assignment to a constant variable`. 

> So I can't change it, goood

Let's look at another example:

```javascript
const person = {
  name: 'chris'
}

person.name = 'cross'; 
```

This works without a problem :)

> Wait whaaat. You said the value couldn't change?

Did I say that? I didn't say that. I said the word `const` sounds like it. What `const` means is that there is a *read-only* reference, i.e the reference can't be reassigned. I never said it can't be changed. Look at this for clarification:

```javascript
const person = {
  name: "chris",
};

person = {
  name: 'chris'
}
```

The above gives an error. `Cannot assign to a constant variable`. 

> Hmm ok, can I make it immutable?

Well you can use `Object.freeze()` like so:

```javascript
Object.freeze(person)

person.name = "cross"; 

console.log(person.name) // 'chris'
```

> Great so there is a way to make everything immutable

Weeell.

> Well what?

It only *freezes* on the first level. Consider this code:

```javascript
const person = {
  name: "chris",
  address: {
    town: 'London'
  }
};

Object.freeze(person)

person.name = "cross"; 
person.address.town = 'Stockholm';

console.log(person.address.town) // Stockholm
```

> But but.. is there no way to freeze it?

You would need a deep freeze algorithm for that. Ask yourself this though, do you need that? I mean in most cases your constants are usually primitives.

> ...

To be fair this is a little how `const` works in other languages as well. I mean in C# it's `static readonly` if you want something immutable and locked reference, in Java you need `final`.

> Yea yea whatever

## -5- There's life after function invocation

Let's look at the following piece of code:

```javascript
function aFunction() {
  let name = 'chris';
  console.log(name) // prints chris
}

console.log(name)
```

Nothing special with it, it doesn't know what `name` is in the last `console.log()` cause it's outside the function. Let's modify it slightly:

```javascript
function aFunction() {
  let name = "chris";
  return {
    getName() {
      return name;
    },
    setName(value) {
      name = value;
    }
  }
}

const anObject = aFunction();
console.log(anObject.getName());
anObject.setName("cross");
console.log(anObject.getName());
```

At this point it prints `chris` calling `getName()`, ok you might think it was bound to a value. Then you call `setName()` and lastly you call `getName()` again and this time it prints `cross`. So why is this surprising? Well think about how a function normally works, you call it and the variables in it seize to exist. Now look at the above code again and notice that the `name` variable seems to still exist long after the function has stopped executing. This is not really surprising if you compare it to a language like Objective-c for example. You are then used to referencing counting, if some part of the code is no longer referencing something it is garbage collected. You are clearly still referencing it via the `anObject` variable. 

But still, if you come from an OO background you might be used to objects holding a state and that the state lives on the object itself. In this case, `name` lives in the lexical environment outside of the object, that's trippy right? ;)

The easiest way to think about this one is object creation with private variables. It's also how I create objects more and more these days.. Nothing wrong with classes though, whatever floats your boat :) 

## Summary

I'd love your comments on other things that may surprise you/trip you up or makes your life better. Cause that is true for me about a lot of things JavaScript - I type a lot less.