Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 9, 2022 09:11 am GMT

Does JS function's 'this' have a default value?

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 page about .map() method of the array prototype and met one paragraph witch hooked my attention:

second params in .map()

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:

[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

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:

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

Spec time!

Now it is time to open the ES specification 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 which is responsible for default this value. There are several steps but 2 of them are main:

OrdinaryCallBindThis steps

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;

Step 5 says that if our function is called in strict mode then thisValue becomes thisArgument and default value for this is not applicable.

function f (){   'use strict'   console.log(this)}f.apply(undefined)// undefined

Step 6 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).

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:

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 strict mode function accepts any this value without any modifications. A non-strict 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 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:

// Callback functionmap(callbackFn)map(callbackFn, thisArg)

that second parameter may be used instead of .bind() method for a callback function.


Original Link: https://dev.to/smlka/global-object-is-just-a-default-value-of-js-functions-this-14hp

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To