Does JS function's 'this' have a default value?
Tags: javascript, webdev, programming
Published: 2022-08-09 09:11:00

## Disclaimer
There are 1000000 articles about **this** in JS. I think it is perfectly fine to add one more.  

## Second parameter of Array.prototype.map
Recently I have checked the [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) page about _.map()_ method of the array prototype and met one paragraph witch hooked my attention:

![second params in .map()](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d6caywu33b4jkv4q7xr7.png)

where _thisArg_ is a second parameter of .map() method **(1)**

The second sentence says - "_Otherwise, the value **undefined** will be used as its **this** value._" So, let's do a quick test and pass inside _.map()_ only a callback:

```js
[1,2,3].map(function(){console.log(this)})
// globalObject
// globalObject
// globalObject
```

It seems confusing as **this** value is a _global object_ and not _undefined_ when a callback is executing. Actually it is expected as the callback is executed in **non-strict mode**. Why then the phrase says _undefined_?

Nevertheless, the phrase makes sense, especially, if we pay attention to the line - "_The **this** value ultimately observable by callbackFn_".

So, what "ultimately observable" does mean? 

## Default value of function's this
Let's create a simplest function ever and try to call it by _.apply()_ method. The _.apply()_ method allows us to set **this** value explicitly and let's set **this** as _undefined_

```js
function f (){
   console.log(this)
}

f.apply(undefined)
// globalObject
```
So, it is possible to conclude that function _f_ ultimately observes _globalObject_ value in **this** and not _undefined_ value we explicitly pass. In my opinion we may compare such behaviour with default function parameters:

```js
function f(a=globalObject){
    console.log(a)
}

f();
```

## Spec time!
Now it is time to open the [ES specification](https://tc39.es/ecma262/) just to be sure that we do not miss any cases.

I really would like to make your life easier, so there is an abstract operation [OrdinaryCallBindThis](https://tc39.es/ecma262/#sec-ordinarycallbindthis) which is responsible for default **this** value. There are several steps but 2 of them are main:

![OrdinaryCallBindThis steps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8f4tmnbv2m4jfegpa3e1.png)

Let's pay attention to 2 variables on the pic:
- _thisArgument_ - is a passed value in a function;
- _thisValue_ - is an ultimately observable value by a function;

<u>Step 5</u> says that if our function is called in **strict mode** then _thisValue_ becomes _thisArgument_ and default value for **this** is not applicable.

```js
function f (){
   'use strict'
   console.log(this)
}

f.apply(undefined)
// undefined
```
<u>Step 6</u> says that if our function is called in **non-strict mode** and _thisArgument_ equals to **undefined** or **null** then _thisValue_ (actual value of **this** inside function) is globalObject (_globalEnv.[[GlobalThisValue]]_ on the pic is just a global object). 

```js
function f (){
   console.log(this)
}

f.apply(undefined)
f.apply(null)
// globalObject
// globalObject
```

So **null** value is also substitute with globalObject default value.

Also it is worth to have a look at _6.b_ which is also valid for **non-strict mode**. There is call of _toObject()_ operation which creates wrapper objects (String, Number, etc) for primitive values of _thisArgument_:

```js
function f (){
   console.log(this)
}

f.apply('')
// String {''}
```
Therefore function's **this** value is always an object type for **non-strict** mode.

##Conclusion
Each time you call a function in JS you pass a **this** value in it. Even if you call a function like _f();_ you still implicitly pass _undefined_ value. A <u>strict mode</u> function accepts any **this** value without any modifications. A <u>non-strict</u> function substitutes _undefined_ and _null_ values with _global object_ and also transform all primitive values in objects. 

Feel free to use that conclusion to win a heart of your next interviewer.

**P.S.**
There is one my old [post](https://dev.to/smlka/easyspec-how-does-settimeout-invoke-a-callback-function-in-a-browser-44kh) about **this** value in a setTimeout callback. In a browser callback's **this** is always _window_ and it does not depend on strict/non-strict mode. The reason is that setTimeout method passes _window object_ not _undefined_ as **this** when executes a callback. Non-strict default substitution just does not work as _thisArgument_ is neither undefined nor null.


**(1)** - Array.prototype.map() method has a second optional parameter:
```js
// Callback function
map(callbackFn)
map(callbackFn, thisArg)
```
that second parameter may be used instead of .bind() method for a callback function.