The connection between `this` and its calling context

Is all information from its call site accessible to a function?

I was under the impression that a function would have access to the scope of its call site, but I could be mistaken. Any feedback and explanation would be greatly appreciated.

function bar() {
    // call-stack is: `bar`
    // so, our call-site is in the global scope
    let a = “heyo”;
    console.log( “bar” );
    foo(); // ← call-site for `foo`
}

function foo() {
    // call-stack is: `bar` -> `foo`
    // so, our call-site is in `bar`
    console.log( “foo “ + this.a );
}
bar(); // ← call-site for `bar`

In this scenario, the value returned by this.a is undefined. Shouldn't it have access to the variable a since its call site is where a is declared?

Answer №1

When you use the this keyword in the foo() function, it refers to the context in which the function is called. In this particular snippet, it is being called in the global context where the variable a is not defined, so the result is undefined.

It's worth noting that you declared a using let, which creates a block-scoped variable. If you had declared a outside of the function using var, it would have been created as a variable in the global scope.

In my example, I created an object with properties a and a method called foo. When you call obj.foo() on the obj object, the this keyword will refer to the obj object. Since I declared a using var globally, when invoking foo(), it will print the value of a from the global scope:

var a = "from global";

function bar() {
   let a = "heyo";
   console.log( "bar" );
   foo(); 
   let obj = {a : "from obj", foo};
   obj.foo(); 
}
function foo() {
   console.log( "foo " + this.a );
}
bar(); 

Answer №2

Initially, the inquiry provided did not include this at all, which is intriguing considering it is the singular exception to the issue at hand.

In JavaScript, lexical scope reigns supreme. This means that functions can access the scope in which they are defined, rather than accessing values randomly scattered throughout the current stack.

const rememberX = (x) => () => x;
// a function that accepts a value and returns another function
// when the inner function is called, it returns the original value

let x = 5;
let x42 = rememberX(42);
let x10 = rememberX(10);
x = 20;

x42(); // 42
x10(); // 10

The magic of closure stems from lexical scoping, enabling the functionality seen above. This distinction sets JavaScript apart from other languages under normal circumstances, leaning more towards functional programming principles.

Curiously, this breaks this rule as the sole outlier. It defies the norm by being exceptionally late-binding and determined at the exact moment of execution.

class Person {
  constructor (name) {
    this.type = "person";
    this.name = name;
  }

  sayHi () {
    console.log(`${this.name}, the ${this.type}, says “Hi”.`);
  }
}


const bob = new Person("Bob");
bob.sayHi(); // "Bob, the person, says “Hi”."

const spot = {
  type: "dog",
  name: "Spot",
  sayHi: bob.sayHi
};

spot.sayHi(); // "Spot, the dog, says “Hi”."

bob.sayHi.apply({
  type: "ape",
  name: "Grape"
}); // "Grape, the ape, says “Hi”."
// apply is a method that all functions have,
// which sets `this` for this invocation


const bind = function (method, overriddenThis) {
  return function (...args) {
    return method.apply(overriddenThis, args);
  };
};
// bind also exists as a method on functions,
// to prevent `this` from being overwritten, using closure

const sayHi = bind(bob.sayHi, bob);
sayHi.apply(spot); // "Bob, the person, says “Hi”."

This explains why your stack-based calls may not yield the expected results, sheds light on the behavior of this, and offers solutions to navigate around it.

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

What is the process of transferring information to a property in JSON within a Jade (Pug) file?

Initially, I transmit data to a Jade template using Node.js. app.get('/', function(req, res){ var arr = new Array( {firstname: 'Gil-dong', lastname: 'Hong'}, {firstname: 'Yeong-sil', lastname: &a ...

Merge floating and absolute positioning techniques

Creating a calendar exhibiting all events in one div requires precise positioning based on the values of top and height. Let me demonstrate this concept. In the image below, both 6am events are aligned vertically. This alignment issue can be resolved by u ...

When I specify the type for the function parameter, an error occurs when I attempt to execute the function

When I assign a generic type to the function parameter and try to call the function, an error message pops up stating "This expression is not callable. Type unknown has no call signature." function a() { return 'abc' } function fun<T>(x: T ...

What is the best way to choose an Animatedmodal that can showcase various demos while using just one ID?

I am currently customizing my website and utilizing the AnimatedModal.js framework. I have successfully displayed content in one modal, but encountered difficulty when attempting to create multiple modals as they all share the same ID. My question is, how ...

Encountering issues in parsing JSON for PhoneGap Application

I've been struggling with parsing JSON data for a unique PhoneGap application that is dynamically generated by a localStorage variable. The PHP script is functioning properly, but the JavaScript code seems to be encountering issues when trying to pars ...

What is the best way to show static files from the backend in a React application?

Currently, my setup involves a React application connected to an Express-Node.js backend through a proxy. Within the backend, there are some static files in a specific directory. When I make requests and embed the response link in the "src" attribute of an ...

Exploring a collection of objects housed in a json document

Currently, I'm looking to retrieve a collection of objects using JavaScript from a JSON file that resides on my website. While I could easily embed the array of objects directly into my JavaScript code, I am interested in understanding how to work wit ...

Unlock the full potential of `enableReinitialize: true` by utilizing the options `destroyOnUnmount: false` and `forceUnregisterOnUnmount: false` in a

I am currently working on a wizard form using redux-form/immutable for creating and updating a form. An issue I'm facing is that when moving from tab1 to tab2 in the wizard form, the state (user inputs) in tab1 gets lost. I have experimented with di ...

Attempting to successfully upload this Angular 7 form to my TypeScript code. Making use of ngForm and [(ngModel)] to achieve this

I am having trouble passing form information using the onSubmit() function. It seems to be undefined when I try to execute it initially. Could there be a syntax error that I'm missing? <form class="gf-formbox" name="credentials" (ngSubmit)="onSubm ...

The event was triggered, however, some sections of the code did not run

I am currently working on a project called lan-info on GitHub. Here is the code snippet that I am using: let arpSweepCommand = './arpSweep.sh'; app.get('/arp', (req, res) => { console.log('we have a working signal!'); ...

Substitute the temporary text with an actual value in JavaScript/j

Looking to customize my JSP website by duplicating HTML elements and changing their attributes to create a dynamic form. Here is the current JavaScript code snippet I have: function getTemplateHtml(templateType) { <%-- Get current number of element ...

Transform the string by eliminating any spaces and new lines before converting it into a JSON object

I need assistance with converting the given string into a JSON object. Here is the string: {\"Warranty\": [ \n { \n \"Name\": \"test\", \n \"Type\": \"test2\", \n \"Months\": ...

What is the method to determine the size of a Map object in Firestore database?

I currently have two elements within a document: an empty array, and a map object containing three components. If the array is empty, it transforms into type array. In this case, I can execute console.log(vehicles.Motorcycles.length) to receive a return of ...

Combine rows with the same value in the first column of an HTML table

My HTML table has dynamic content, and I need to merge rows in the first column only if their values are identical. You can see an image of the table here. Specifically, if the values in the first column match, those rows should be merged together while le ...

Images copied using Gulp are often distorted or incomplete

There is a simple task of moving an image from one folder to another. gulp.task('default', function () { return gulp.src('./img/*.*') .pipe(gulp.dest('./image')); }); Previously, everything was running smoothly, b ...

The issue of race condition in Node.js programming

I've been diving into the documentation, but I'm struggling to figure out what's going on here. I have two functions: one downloads a CSV file via a URL, and the next function takes that CSV file and converts it to JSON FileDownload.js co ...

retrieving the element's height results in a value of 'undefined'

I am attempting to get the height of a specific element, but unfortunately I keep getting undefined. Here is what I have tried: var dl; $(window).load(function(){ dl = $("#dashboard_left").height(); }); $(document).ready(function(){ alert(dl); } ...

Tips for avoiding the "Confirm Form Resubmission" pop-up?

Is there a way to clear form data after submission in order to prevent errors from appearing upon page refresh? For reference, please see the image below (taken from Chrome): The dialog box displays the following message: The page you're trying t ...

Sending information back to the server without causing a postback, all while remaining unseen

I have a straightforward JavaScript function on my ASP.NET page that writes data to a hidden field. However, in order to retrieve this data the form needs to be submitted back to the server. The issue is that submitting the form causes the page to reload ...

Is there a way to condense my child table directly below its parent column?

When attempting to collapse the "child tr" within the "tr" in my code, the collapse is not positioning correctly underneath its parent tr. While it works fine in a JSFiddle, the issue arises when using my editor and live preview. In this scenario, both "ch ...