Can you explain the use of the 'this' keyword in map() and call() functions?

Recently, I've been revisiting my understanding of how to use call() and map() with a NodeList in JavaScript.

It was quite easy to find information on how call() works, and there are plenty of examples of how it can be used with map().

However, while browsing through MDN, I discovered that the map() function can also accept a second argument to set the this keyword for map(). Or at least, that's what I believe it does.

I decided to test this out with simple arrays:

var numbers = [1, 2, 3];
var letters = ['a', 'b', 'c'];

And a basic function that will be passed as a parameter to map():

var effector = function (x) {
    console.log(x);
}

What confuses me is why these two function calls result in different outputs:

numbers.map(effector, letters);
numbers.map.call(letters, effector);

I expected both to log the letters to the console, since the this keyword should reference them (or their objects) respectively.

After further investigation, I experimented with a modified version of the effector function:

var effector = function () {
    console.log(this);
}

Again, testing it with:

numbers.map(effector, letters);
numbers.map.call(letters, effector);

Under the assumption of being in "use strict" mode, the first call logs letters and the second call logs undefined.

Yet, I still expected both calls to produce the same result.

What am I overlooking?

EDIT:

I came across information about how the .map method can be polyfilled on MDN, showcasing how the second parameter of callback.call() is utilized in it.

I presume that ultimately, even callback.call() should have the same this reference as in .map.

MDN - map

Answer №1

In this situation, there are two different contexts for the this reference:

  • this within the execution context of the map function
  • this within the execution context of the callback function

These two contexts are independent of each other.

The second argument of map determines the value of this for the callback function. If this argument is not provided, the default value is undefined (not the array).

On the other hand, the first argument of map.call determines the value of this for the map function, which in turn affects the array being iterated.

This behavior is consistent with the polyfill provided on mdn, where O represents the value of this for the map function, and T represents the value of this for the callback function. These values are typically different.

map versus forEach

Although unrelated to your query, it is important to note that map should only be used when you are actually mapping values. This method is designed to create a new array where each value is mapped by applying the callback function to the original value at the same index.

If you simply need to iterate over the array values without any mapping, it is recommended to use the forEach method or a for...of loop. Both of these options work directly on NodeList without requiring .call.

Answer №2

The distinction between using numbers.map(effector, letters) and

numbers.map.call(letters, effector)
lies in the specific function that the this keyword is set to when the code is executed.

According to MDN, the second argument provided in the first version determines the value of this within the callback function. This means that in numbers.map(effector, letters), the this within effector will be assigned the value of letters. However, since effector does not specifically reference the value of this, the argument has no significant impact and the contents of numbers are simply outputted.

On the other hand, in the scenario of

numbers.map.call(letters, effector)
, the this keyword of numbers.map is set to letters. This effectively causes the map method to execute on letters instead of numbers.

In both cases, the key factor lies in determining the function to which the this keyword is anchored: either effector or numbers.map.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Combining JSON arrays based on property matches in Node.js

I am working with two JSON arrays in Node.js. const arr1 = [{id: 1, name: 'X'}, {id: 2, name: 'Y'}, {id: 3, name: 'Z'}, {id: 4, name: 'W'}]; const arr2 = [{id: 1, value: 80}, {id: 2, value: 30}, {id: 3, value: 76}] ...

Is your PHP, MySQL array not displaying properly in a single HTML table despite multiple queries being made?

I found a code snippet on this website, which I utilized as shown below $data = array(); while($row = mysql_fetch_assoc($num1)) {$data['row'][] = $row;} while($row = mysql_fetch_assoc($num2)) {$data['row2'][] = $row;} $count = ...

My attempt at deploying my personal React App project on Vercel was unsuccessful

// encountering error during deployment on Vercel npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: @testing-library/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e99b8c888a9da9d8da ...

Using Javascript to pass the value of a selected checkbox

I am having an issue with passing a row value to a different function when a user clicks on a checkbox in the last column of a table. The code I have written doesn't seem to be firing as expected. Can anyone help me figure out what might be missing in ...

Ways to revert to the initial state in React.js

Check out my codeSandbox project here: https://codesandbox.io/s/bold-lederberg-d2h508?file=/src/Components/Products/Products.js I'm having trouble getting the items back to their original presentation when clicking on "default" - sorting by price wor ...

What is the best way to access the URLs of files within a Google Drive folder within a React application?

I've been working on a react app that's relatively straightforward, but I plan to add a gallery feature in the future. To keep things simple for the 'owner' when updating the gallery without implementing a CMS, I decided to experiment ...

Creating an associative array in PHP using data from a CSV or TXT file

Having an issue with associative arrays in PHP when trying to read from a text file. If I define the arrays manually like this: $logins = array('user1' => '1234','user2' => '2345','user3' => &apo ...

The jQuery UI Sortable functions are being triggered at lightning speed

I am currently working on a project where users can create a seating chart, add rows and tables, and move the tables between different rows. The functionality for adding rows and moving tables already exists in the code. However, I am facing an issue where ...

Tips for extracting double values from a scanner and storing them in an ArrayList

Scanner input = new Scanner("2.30 4.50 10.35 200.61 82.00"); ArrayList<Double> values = new ArrayList<Double>(); Although I don't need to take input from the mouse, I must utilize a scanner to populate my values. I am experimenting with a ...

Implementing AJAX mysqli interaction in PHP following the MVC design pattern

Today I'm encountering yet another AJAX-related error. I am in the process of developing a user registration system using AJAX and PHP, following MVC architecture. Previously, I successfully built a login system without AJAX that functions flawlessl ...

Extract portions of the date into individual variables

My current project involves creating a front-end interface for data stored in a JSON database. The date information is saved in the following format: 12/31/16 I am trying to extract each of these values individually. Is there a method to assign variabl ...

Strange yellow border appears when key is pressed in Quasar's QLayout

While working on a project with the quasar framework and electron.js, I encountered a strange bug where pressing a key causes the application frame to display a persistent yellow border. This border cannot be overridden, removed, or selected using devtools ...

A simple way to verify which option has been chosen has been altered

I am examining the code snippet below: <select class="select" id="choice-item" aria-invalid="false"> <option value="#opt0" selected="selected">32 bits</option> <option value="#opt1">64 bits</option> </select> M ...

Tips on managing ajaxStart and ajaxStop events the Angular2 way

I am seeking a way to trigger events similar to JQuery's ajaxStart and ajaxStop. While I found a partial solution on how to set default HTTP headers in Angular 2 here, I have managed to handle the ajaxStart event for now. Does anyone have any soluti ...

Do we need to utilize a server folder in Nuxt 3 if we have API endpoints?

In Nuxt 3, there is a dedicated server folder containing an api subfolder. Why should we utilize this when we already have API endpoints built with a server-side programming language like Laravel? Are they linked in any way? For instance, consider these ...

Updating components reactively in Vue.js when a click event occurs

I have a dilemma with my component that allows users to add or remove an item from their favorites. While the functionality works smoothly, there is no visual indication for the user to know whether the item has been added to favorites or not. Currently, I ...

What is the best way to retrieve all objects from this data model?

I am looking to collect all the Model Objects from the data structure provided below. const PRODUCTS = [ { brand: 'Audi', allSeries: { serie: 'A3', allModels: [ { model: ' ...

The React-loadable alert indicated a discrepancy in the text content

Utilizing react-loadable for dynamic JS module loading is part of my process. With server-side rendering already set up and functioning correctly for react-loadable, I am encountering an issue on the client side. Upon page load, a warning message appears i ...

The amalgamation of geometries using BufferGeometryUtils results in variations from the original model

I have encountered an issue when attempting to merge GLB model geometries with three.js using BufferGeometryUtils.mergeBufferGeometries. The new merged geometries do not always align perfectly with the original model. Furthermore, some of the geometries e ...

Is there a way to track whether a user has logged into the Google Chrome browser using cookies?

While the LSID cookie can indicate if a user is logged into a Google account, it cannot be reliably used to determine if someone is signed into the Chrome browser because it may also appear when a person is signed into Gmail without being signed into Chrom ...