Utilize a function as a parameter

I am struggling to figure out how to make this function pass by reference in my code. Is there a way to achieve this?

var Class = function() {
    var callback1;
    var callback2;

    function buildStuff(data, callback) {
        element.onclick = function() {
            doStuff(callback);
        };
    }

    function doStuff(callback) {
        callback();
    }

    return {
        "setCallback1":function(fn) {
            callback1 = fn;
        },
        "setCallback2":function(fn) {
            callback2 = fn;
        },
        //may rebuild with different data, but same callback
        "buildFoo":function(data) {
            buildStuff(data, callback1);
        },
        //may rebuild with different data, but same callback
        "buildBar":function(data) {
            buildStuff(data, callback2);
        }
    };
}

function main() {
    var object = Class();
    object.setCallback1(function() {
        //do stuff
    });
    object.setCallback2(function() {
        //do something else
    });
}

After clicking on the element, the callback variable is returning as undefined. I was expecting it to be the anonymous function set using the setCallback function, but it seems the user click occurs before the setCallback function is called.

Thank you for any help!

UPDATE: I realize now that I need to dynamically set what callback equals. So simply removing the callback parameter from buildStuff won't work in my situation.

UPDATE2: Apologies for the confusion earlier. The buildStuff function is actually a private member function within the class (utilizing the module pattern) and is called multiple times. Depending on the object being built, it requires a different callback. The callback is set externally to the class, hence the need for dynamic assignment. I've made some adjustments to my code to clarify this. Sorry for any misunderstandings.

Answer №1

The click handler created within the buildStuff function forms a closure over the local variables. Initially, when you pass the callback to the buildStuff function, it is undefined. This leads to the other callback variable being overshadowed, resulting in the undefined value being displayed, instead of the desired state of the other callback variable.

To address this issue, refrain from passing a parameter to the buildStuff function. This will allow the closure to be formed and capture the intended callback variable.

function buildStuff() {
    element.onclick = function() {
        doStuff(callback);
    };
}

Consider the following scenario;

  1. Your global variable callback holds a value (specifically undefined in this case).

  2. Upon calling buildStuff within main(), the value pointed to by callback (which is undefined) is passed as an argument to buildStuff

  3. The click handler forms a closure over local variables + other variables in the scope (note the local callback overshadows the global callback). Consequently, the callback within your event handler becomes undefined.

  4. Subsequently, you invoke setCallback. This function alters the value that the global callback variable points to using the = operator. At this point, the global callback and local callback are referencing different values, explaining why the update to the callback in the event handler is not reflected.

    In such circumstances, you may wish to modify the value being referenced by callback to ensure other variables pointing to it are updated as well. However, JavaScript does not allow for this type of operation.

Answer №2

Aha, you have indeed called buildStuff prior to setCallback.

The current state of callback (undefined) will be utilized.

If you wish to invoke buildStuff with different callbacks, simply go ahead and do so, thus removing the redundant setCallback:

function buildStuff(callback) {
    element.onclick = function() {
        doStuff(callback);
    };
}

function doStuff(callback) {
    callback();
}

function main() {
    buildStuff(  
      function() {
        //perform a task
      }
    );
}

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

Javascript challenges for beginners in coding world

After running the code snippet, I encountered the following error messages: at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Fun ...

How can I effectively refresh the provider_token / access token for Discord in NextJS with Supabase Auth?

Currently, I have encountered an issue with my NextJs project using Supabase Auth for authentication. I am currently utilizing the Discord provider and everything works fine initially. However, after a few minutes, the session object gets updated and the p ...

Adding styles dynamically using methods is not supported in Vue.js

When it comes to adding styles to an HTML element from methods, I ran into a small hiccup. Here's what I tried: <div class="add-profile-img" v-bind:style="getBackgroundImg()"> The method in question is: getBackgroundImg: function() { return { ...

Is there a method to dynamically incorporate a new editable textfield row in a react table?

Is there a way to dynamically add an editable row of text fields to a table in React? Currently, when I click on the "Add" button, a new row is added to the table but it's not editable by default. The logic for adding a new row is implemented inside t ...

Searching for two distinct nested key values in Ramda

I am new to Ramda and wondering if it is possible to retrieve two different key values at the same level of an object. Below is the code I have added: In this scenario, the object 'list' contains keywords 'users' and 'employee&ap ...

The error encountered in the Node crud app states that the function console.log is not recognized as a

I am attempting to develop a CRUD application, however, I keep encountering an error message that states "TypeError: console.log is not a function" at Query. (C:\Users\Luis Hernandez\Desktop\gaming-crud\server\app.js:30:25) h ...

Issue - Basic Data Protection and Unscrambling - Node.js

I have been working on some basic code to encrypt and decrypt text, but I keep encountering an error when using the .final() function of createDecipherIV. I have tried experimenting with different encodings like Binary, Hex, and base64. Node Version: &apo ...

Tips for postponing the execution of inline javascript

Main page <script> $.ajax({ type: 'GET', url: 'ajax.php', context: document.body, success: function(data) { $("#content").html(data); } }); </script> <div id="content"></div> Ajax ...

What external libraries does Angular 4 utilize during execution, aside from RxJS?

Angular 4 relies on RxJS types in its public API and also internally depends on RxJS. It would be beneficial to explore if Angular utilizes other external packages for certain functionalities, allowing us to incorporate them into our own projects. This ap ...

The redirect function is failing to carry the "req" parameter

Express Routes Troubleshooting app.get('/auth/google/redirect', passport.authenticate('google'), (req, res) => { console.log('req.user:', req.user) //>>>>>Outputs {username: 'bob', id: '.. ...

Adding Bootstrap to container-specific styling in SCSS

I am currently in the process of upgrading to the most recent version of reactstrap & Bootstrap. Previously, I had reactstrap in my package.json file and downloaded Bootstrap SCSS in my client/src/styles/bootstrap directory. Now, my updated package.json c ...

Font in Three JS not loading properly

I'm attempting to use TextGeometry in my project to incorporate text. var shape = new THREE.TextGeometry( 'Hello, World!', { size: 60, height: 20, curveSegments: 3, font: 'helvetiker', weight: ' ...

Issue with retrieving the current location while the map is being dragged

How can I retrieve the current latitude and longitude coordinates when the map is dragged? I've tried using the following code: google.maps.event.addListener(map, 'drag', function(event) { addMarker(event.latLng.lat(), event.la ...

Managing global errors and intercepting requests in AngularJS can be easily achieved by utilizing $resource interceptors and global handlers for

My question pertains to the interceptor(responseError) of $resource. It is essential to note that I am working with angularjs version V1.3.6. The Issue: app.factory('authInterceptor',['$q', '$location', '$log', fun ...

Guide to refining a JSON array using a pre-established list

I'm in need of assistance figuring out how to accomplish the following task: Below is the code snippet I am working with: public class Data { public string FirstName; public string LastName; public int Age; } var data = new Data { //this objec ...

Save a text as a CSV file while also preserving any commas within the

I am trying to export a string to csv format while ensuring that commas inside the string are not treated as separators. For example: [{"name":"ALIASED_LINE_WIDTH_RANGE","value":{"0":1,"1":1}}] Even when ...

The file extension validation function is not functioning correctly on Windows, however it is successfully working as expected

async upload( @UploadedFile() file: Express.Multer.File, @Body() body: FileUploadDto, ) { const forbiddenExt = [ '.exe', '.bat', ]; const fileName = file.filename || f ...

What could potentially be the reason behind the incapability of the next.js Image component to transform the svg into a

Unique Context I recently developed a minimalist Hero + Navbar using Next.js. The site utilizes the powerful next.js Image component to display images. Surprisingly, all three images on the website, which are in .webp format, load instantly with a size of ...

Transition one background image into another using background positioning

Snippet of code: https://jsfiddle.net/foy4m43j/ HTML: <div id="background"></div> CSS: #background { background-image: url("http://i.imgur.com/hH9IWA0.png"); background-position: 0 0; background-repeat: repea ...

What is the process for modifying the logfile path in phantomjs using selenium?

Is there a way to modify the default --webdriver-logfile parameter that selenium passes to phantomjs when using them together? This is the line in the selenium log: 11:06:06.960 INFO - arguments: [--webdriver=14380, --webdriver-logfile=<ROOT PATH DELE ...