0

So I have this function

window.initFloof = function (callback) {
    ....
    let val1 = 22; // Sample value
    if (callback !== null) {
        if (typeof callback === "function") {
//          callback(val1); // Both are working but arguments don't get passed.
            window[callback](22); // Both are working but arguments don't get passed.
        }
    }
}

I am calling the above function as below

window.initFloof('callbacky');

Now the callbacky function.

window.callbacky= function (val1) {
    console.log(val1); // This is giving Undefined, while I am expecting a `22` as per the above example. Alerts if set, are triggering btw which means the function is being executed.
};

EDIT:-

OK guyz, Extremely sorry my bad, I was actually using

if (typeof window[callback]() === "function") {

...this got lost in distilling my function down for posting here. I agree It was my bad, feeling goofy now.

And also I realize where my problem was, In the above line, Instead of checking if the function existed It was actually being executed and since the condition was not being met, the actual line of code window[callback](22); was just being skipped over, hence the title, argument was not being passed.

Mohd Abdul Mujib
  • 13,071
  • 8
  • 64
  • 88
  • 4
    `('callbacky')` is of type string. Try `window.initFloof(callbacky);` – Rajesh Aug 27 '18 at 13:47
  • 1
    Lemme get a demo together real quick. – Mohd Abdul Mujib Aug 27 '18 at 13:48
  • 2
    Also note that bleeding variable/functions on `window` is a very bad conventions and should be avoided unless necessary – Rajesh Aug 27 '18 at 13:49
  • [Here](https://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string) is where I got the idea of executing the functions based on string, since the functions are being dynamically made & called I can't hardcode them. – Mohd Abdul Mujib Aug 27 '18 at 13:53
  • 1
    Your current code would work but this check: `if (typeof callback === "function") ` is breaking it. You are checking type of passed value. You should check: `if (typeof window[callback] === "function") ` – Rajesh Aug 27 '18 at 13:55
  • @9KSoft Is this some sort of JSONP function you're trying to make? What's your usecase for passing a function as a string? – Madara's Ghost Aug 27 '18 at 13:56
  • 1
    Why are you "dynamically making functions"…? Either you have a set of predefined functions and you choose one (in that case, use a dictionary/object to translate a string identifier into a function), or you have a defined name whose content changes (e.g. passing callback functions). It's… unusual that both the function *and* their names are dynamic. That's basically madness. – deceze Aug 27 '18 at 13:56
  • @deceze That's why I asked about JSONP, it's the one case I can remember that you need to have a function's name as a string readily available both for passing to a request and globally available on `window`. – Madara's Ghost Aug 27 '18 at 13:58
  • I'll put this on hold until all the vagueness is cleared up with the promised demo… – deceze Aug 27 '18 at 13:59
  • Btw here is the [Demo](https://codepen.io/MohdAbdulMujib/pen/NLNzYE?editors=1010) – Mohd Abdul Mujib Aug 27 '18 at 14:24
  • @MadaraUchiha No I am not using this for Jsonp, but its somewhat similar since in my use case the function name is being generated by the framework, which is tightly knit with the js. I know, its not the most optimal approach, but gotta live it. :) – Mohd Abdul Mujib Aug 27 '18 at 14:30
  • @Rajesh On point bro, this exactly was my problem, and my goofey mistake made it twofold :) – Mohd Abdul Mujib Aug 27 '18 at 14:31
  • @deceze Thanks for your advice, will keep in mind for future projects, for the current one, I have to live with it. alteast until next refactoring sprint. – Mohd Abdul Mujib Aug 27 '18 at 14:33

2 Answers2

4

Your specific problem is that the argument you're passing is a string, and you have a function that checks if it's a function, which it is not, therefore you aren't entering the if block.


However

This isn't PHP. Functions aren't referenced by passing the strings and having them available on the global scope.

In JavaScript, functions are normal objects, so just pass the function itself directly as the callback.

window.initFloof = function (callback) {
    ....
    let val1 = 22; // Sample value
    // null check is redundant, null is of type "object".
    if (typeof callback === "function") {
        // No need for window[..., callback is a reference to a function.
        callback(22); // Call the callback object with the parameter.
    }
}

window.initFloof(window.callbacky);

Should you need to dynamically pass a function's name (or rather, the name of the property on window by which it is referenced), you can build on the code above in this fashion:

function initFloofStringCallback(functionName) {
  return initFloof(window[functionName]);
}

But that's a bit of code smell. In general, relying on the availability of global functions is not good practice.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • 2
    Nitpick: `window[callback](22)` *can* certainly work, but it's the icky no-no way of passing callbacks… – deceze Aug 27 '18 at 13:48
  • I've made an edit :) – Madara's Ghost Aug 27 '18 at 13:49
  • @deceze `window[callback](22)` will never work as callback refers to `window.callbacky` and hence `window['window.callbacky'](22)` is invalid – Ankit Agarwal Aug 27 '18 at 13:52
  • @Ankit OP is showing the use as `window.initFloof('callbacky')`, which *would* work. You just need to match whether you're expecting and passing a string or a function. – deceze Aug 27 '18 at 13:54
  • 1
    That will still not work because at that case it is a `String` type and ` if (typeof callback === "function")` will be `false` so it will never execute the code `window[callback](22)` hence it will certainly not work at any case @deceze – Ankit Agarwal Aug 27 '18 at 13:55
  • @Ankit Sure. I just wouldn't take OP's code *that* seriously in that regard and rather ask for a clear MVCE. Surely not "both ways work" with the code as given, as claimed. – deceze Aug 27 '18 at 13:58
  • @AnkitAgarwal absolutely, I was actually using `typeof window[callback]() === "function"` for the condition which was executing the function right inside the condition .......and my apologies for the goofup. – Mohd Abdul Mujib Aug 27 '18 at 14:36
  • 1
    @MadaraUchiha On a lighter note, I really liked the Black Panther: "We don't do that here" vibe IYKWIM :P – Mohd Abdul Mujib Aug 27 '18 at 14:43
1

There are several issues in your code:

  1. You have to call window.initFloof like window.initFloof(window.callbacky); and not with passing a value in single quote.
  2. This call should be done after the assignment of the function to window which is window.callbacky. Once you have declared the function here then you will be able to pass that as a parameter of window.initFloof
  3. Inside the function window.initFloof the callback refers to the function window.callbacky so you simply need to do callback(22);.

window.initFloof = function (callback) {
    let val1 = 22; // Sample value
    if (callback !== null) {
        if (typeof callback === "function") {
            callback(22); 
        }
    }
}
//this declaration is first
window.callbacky= function (val1) {
    console.log(val1);
};
//this call is second
window.initFloof(window.callbacky);
Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62