PHP executed function as function's parameter - javascript

Is it in PHP possible to pass a executed function as function's parameter, so that the result of the function will be hand over but not a callback function object?
Without touching the scope function (no eval or extra magic execution).
Let's say, the parameter I want to give the function is not clear. So there must be a decision for that before given to the function.
Currently this always lookes like this:
$tmp = ($something == $bla)?42:7;
myFunction($tmp);
For such a short decision it is not so problematic. But sometimes there are more then two possibilities. So a if-elseif is needed, or a switch-case.
But it would be so much cleaner to just put somthing like this:
myFunction(function(){
if(...){ return 42; }
elseif(...){ return 7; }
elseif(...){ return 5; }
elseif(...){ return 12; }
else{ return 1; }
});
So without saving it first to a variable.
Just for cleaner code, less $tmp or $trash variables.

Anonymous functions and variable functions should be what you are looking for:
Anonymous functions, also known as closures, allow the creation of
functions which have no specified name. They are most useful as the
value of callback parameters, but they have many other uses.
Anonymous functions are implemented using the Closure class
And a code example:
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
And one more code example, just for the sake of completeness, about how to pass a function name as parameter, and call it aftwerwards:
<?php
function here() {
print 'here';
}
function dynamo($name) {
$name();
}
//Will work
dynamo('here');
//Will fail
dynamo('not_here');
Last example was extracted from here

So with the understanding of anonymous functions (Thanks Lucas Meine ), I found that you can execute a function directly by surrounding it with brackets, followed by parameter brackets that will be empty or not depending on whether you want to give the lower level function some of your variables out of the main context.
In all following examples the output of var_dump is 42.
example without variable parameters
// the function that should later be called
function myFunction($test){
var_dump($test);
}
// function call with a executed function as parameter
myFunction((function(){
return 42;
})());
example with variable parameters
$someVar = 42;
function myFunction($test){
var_dump($test);
}
myFunction((function($tmp){
return $tmp;
})($someVar));
or with the use statement
$someVar = 42;
function myFunction($test){
var_dump($test);
}
myFunction((function() use ($someVar){
return $someVar;
})());

Related

Are functions passed as parameters always callbacks? JavaScript

If I have the code below, where I pass two functions as a parameters into the function sayHi, is this an example of a callback?
I notice there are two ways of running these 'parameter functions': either as below, we I call the functions where they are defined (as arguments), or alternatively where I call the parameter in the sayHi function. Would this be the difference between a callback and an anonymous function?
function sayHi(name, testForTrue) {
if (testForTrue == true) {
console.log(name);
}
}
sayHi(function() {
return 'Zach'
}(), function() {
return true;
}());
Another way I could get the same result, is as below. In this case I am evaluating the functions at a different time? Is there any practical difference between the two?
function sayHi(name, testForTrue) {
if (testForTrue() == true) {
console.log(name());
}
}
sayHi(function() {
return 'Zach'
}, function() {
return true;
});
Yes, functions passed as parameters are always callbacks, even if the intention is that the function is called synchronously (c.f. Array.prototype.map) rather than asynchronously (c.f. window.setTimeout).
In your first code block you aren't of course actually passing functions. You have two immediately invoked function expressions, where the key part in this context is immediately invoked. The function expressions are called at the point they appear in the code and only the results of those expressions are passed to sayHi.
In your first example you're not passing functions, but values; in other words
(function(){ return 3; })()
is just the integer 3.
It is a value obtained calling immediately a function, but this is irrelevant.
When you pass a callback it's the receiver that will call it (or pass it to some other function) and the code will be executed later, and not at the call site.
I guess that would depend on what your callback function is actually doing.
In your examples, all you're really doing is returning a value. That's not really a "function", it's returning one fixed value every single time.
If your function is actually doing a process, or returning a varied result, then I would personally consider it a callback. (The name of it is self-explanatory, really). Your script shouldn't rely on it, rather have it be a handler for the result of the function.
For instance, something like this would be what I consider a callback function:
function doSomething(callback) {
var userInput = prompt("hello, enter a number 1-10"),
hasWon = false;
if (userInput === "3") hasWon = true;
callback(hasWon);
};
With this provided, we can call it like this:
doSomething(function(hasWon){
if (hasWon) alert("Congratz! You guessed my lucky number!")
});

JavaScript closures & callback functions

Can someone clarify this point for me?
Two of my favourite features in JavaScript are closures and the fact that functions are first class objects.
If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function. For example:
doNested();
function doNested() {
var message='Hello';
window.setTimeout(inner, 3000);
function inner() {
alert(message);
}
}
There is no way I can pass a parameter to an outer callback function. For example:
doSeparated();
function doSeparated() {
var message='Goodbye';
window.setTimeout(outer,3000);
}
function outer() {
alert(message);
}
This doesn’t work, of course.
The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?
Thanks
If I want to take advantage of closure in, say, a callback function, then the function must always be an inner function.
That's correct. Every function in JavaScript only has access those variables which are either defined in its own scope or defined in a parent scope1. Therefore, your first example works while your second example doesn't.
The question is, is there any way to pass inner variables to an external function like this, short of adding them to a parameter list?
No, there's no way to do that. Well, technically you could add your inner variable to an object and then bind that object to the external function after which you can access the inner variable from the this context of the external function, but that is no better than passing the variable to the function directly.
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer.bind({
message: message
}), 3000);
}
function outer() {
alert(this.message);
}
Since you are using setTimeout, you can pass extra arguments to setTimeout which will be given to the callback function. This gets rid of the nasty bind:
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer, 3000, message);
}
function outer(message) {
alert(message);
}
Note that both bind and extra arguments of setTimeout don't work in older versions of IE. In that case, you can use currying instead (which in my humble opinion is the best solution aside from your original nested solution):
doSeparated();
function doSeparated() {
var message = "Goodbye";
setTimeout(outer(message), 3000);
}
function outer(message) {
return function () {
alert(message);
};
}
Other than these, there's no other good solution that I can think of. The best solution is your original nested solution.
1 A function doesn't have access to any variable defined in a child scope or else you would be able to access every variable from the global scope.

Javascript/JQuery: Assign a whole line of code to a function parameter?

Is it possible to assign a whole line of code to a function parameter? Take this example:
function testFunc(parameter1){
parameter1;
}
testFunc($(".someClass").text("someText"));
When the function is used with that parameter, can the parameter1 be replaced by the line of code?
I'm new with JavaScript and jQuery, so I'm just curious if this is possible. I did not see any questions like this asked before. But if it was asked, a link to the question would be appreciated. Thanks
Sounds like you are inventing the callback :)
Pass an actual function and call it with ();
function testFunc(callback){
callback();
}
testFunc(function(){$(".someClass").text("someText");});
Yes it can be done , as jQuery will eveluate it and return a object.
The key insight here is that a function can be treated like any other variable.
For example:
var i = 1;
var f = function() { console.log('hello!'); };
Here f is a value, just like i is, but you can invoke it just like any other function:
f(); // prints 'hello!' in the console
Because it is a value, you can pass it to another function:
function g(h) { h(); }
g(f); // prints 'hello!' in the console
Take the time to ensure you understand the above code. I've deliberately used vague names so you can learn the mechanics. Let me know if you have any questions.
Arguments aren't assigned to functions, they are passed/sent/[insert other synonym here].
Anything that is an expression (any code which evaluates to some value) can be passed around.
In your exemple $(".someClass").text("someText") is an expression which evaluates to a jQuery object, so you can use this unit of code as a function's argument without any doubt.
However, if you want to pass around some code which has to be executed as part of an existing function's process, you must use a function expression which encapsulates that behavior.
E.g.
function executor(task) {
task();
}
executor(function () {
//code to be executed by the executor
});
Yes you can pass function callback like regular primitive variable
In your case you should check param type before execution
function testFunc(parameter1){
if(typeof parameter1==="undefined"){
//arguments[0] will fall here
console.log("No arguments case. parameter1 not defined")
}
else //function check
if(typeof parameter1==="function"){
//you can parameter function here.
return parameter1();
}
else{
//regular case value or object, other than function types fall here
console.log("not a function, received param type: "+ typeof(parameter1));
return parameter1;
}
}
$(function (){
//let us say you have below vars
var primitiveVar="test",
fun = function(){console.log("function fun call")};
//no args here
testFunc();
//sending primitiveVar
testFunc(primitiveVar);
//below is your call with jQuery Obj
testFunc($(".someClass").text("someText"));
});

What is going on inside the $.each()?

I am stumbling upon a problem that I have seen before, but that I couldn't solve before. I will likely stumble upon it again in the future, so please, someone explain it to me what is going on?
In the partial snippet of javascript below, I have a function that populates a screen, including an order combobox (twitter bootstrap). When I click on one of the order items in that combobox, it should invoke the function clsModCampaigns.blnCompaniesListReload().
For a reason that I don't understand, once inside the '$.each' iterator, the global object reference 'objModCampaigns' is lost? I get a successful alert '1', but not an alert '2'.
Within the $.each, I would like to use 'objModCampaigns.arrOrderBy' instead of 'this.arrOrderBy', but the $.each iterator only seems to work this way. Why is it working this way??
What is going on with 'this', or with variables/objects assigned in the root of the class with 'this'?
Is $.each just special??
function clsModCampaigns(objSetSystem, objSetModuleBase)
{
objModCampaigns = this;
arrOrderBy = {
intID: 'ID',
strName: 'Name'};
[...]
this.blnScreenCampaignInitialize = function (fncSuccess,fncError, intID) {
$.each(this.arrOrderBy, function (strFieldName, strFieldDescription) {
if(strFieldName != 'datDeleted' || objSystem.blnHasPerm("CAMPAIGNS_DELETED")) {
strOrderByID = "ulCampaignsCompaniesListOrderBy" + strFieldName;
$("#ulCampaignsCompaniesListOrderBy").append('<li>'+strFieldDescription+'</li>');
$("#"+strOrderByID).unbind("click").bind("click", function() {
alert("1");
objModCampaigns.arrCurrentShownCompanies.strOrderBy = strFieldName;
objModCampaigns.blnCompaniesListReload();
alert("2");
});
}
});
return true;
};
}
The code you have is
$.each(this.arrOrderBy, ...);
You want
$.each(arrOrderBy, ...);
The reason for it is the this context on that line is different because it is inside a new function this.blnScreenCampaignInitialize.
This is just a part of how JavaScript works
var message = "hello";
function welcome() {
console.log(message);
}
welcome(); // "hello"
P.S. use var
If you don't use var, you'll be attaching all of your vars to the global object.
function hello() {
foo = "bar";
console.log(foo);
};
hello(); // "bar"
console.log(foo); // "bar"
// Holy smokes! `foo` has escaped our `hello` function!
Compare that to
function hello() {
var foo = "bar";
console.log(foo);
}
hello(); // "bar"
console.log(foo); // ReferenceError: foo is not defined
// much better
Now let's see a terrible example
function a() {
b = 5;
return b;
}
function b() {
return "function";
}
console.log(a()); // 5
console.log(b()); // TypeError: number is not a function
This is happening because we didn't use var properly. We first define b as a function but after running a(), b is now set to 5. The second log statement is the equivalent of trying to run 5() because b is no longer a function.
P.P.S. it's pretty unconventional to prefix your vars with str, int, fnc, obj, or cls in JavaScript.
I understand you're a "VB guy" according to your comments, but that's no excuse for bringing your own conventions to the language. I see in your profile that you're fluent in Dutch, English, German, and French. I would recommend you treat learning programming languages much the same as spoken languages: each of them have their own explicit set of rules and conventions.
Here's a heap of free JavaScript books for you. I hope they can help you learn some more basics.
P.P.P.S. Overall, your function is really big as it is, and I can see you already truncated some of the code with your [...]. The whole thing could probably benefit from some better composition.
If you paste all of your code, maybe someone could help you better.
What is going on inside the $.each() ?
Regarding you question title, I'm trying to answer:
// each function in source
function (obj, callback, args) {
//...
}
Check the source of complete $.each function by yourself, you can see any function's source code just by typing the function name in the appropriate text box (the second on top).
Here in each function, the array/object passed in to the each function (the first argument) is being run through a loop and each value is being passed in to the callback (second argument) and that call back is getting executed like:
callback.apply(obj[i], args);
So, the passed callback in the each function is being executed each time the loop occurs ad the current value in the loop is passed as the argument of callback function along with the third argument args.
If your function function clsModCampaigns(){ //... } is a normal function then this inside this function points to global window object. so just use:
$.each(arrOrderBy, ...);
instead of
$.each(this.arrOrderBy, ...);
Because, arrOrderBy is within the direct scope so arrOrderBy is accessible directrly. For example:
function someThing()
{
var x = 'y'; //<-- this scope (everything inside someThing) is
// global for somethingElse inner function
function someThingElse)(x) //<-- possible to use directly
{
}
}
The keyword this behaves differently depending on the context. Check about this on MDN.

Doing Math in Multiple Javascript Functions

I'm new to the Javascript world and trying to figure out this assignment my teacher assigned. Here is his description of what is expected:
Build a function that will start the program. Please call it start()
From the start() function, call a function called getValue()
The getValue() function will get a number from the user that will be squared.
Also from the start function, call a function called makeSquare()
The makeSquare() function will square the number that was received by the user in the getValue() function.
Make sure that you display the results of squaring the number inside of the makeSquare() function.
Here is what I have so far:
function start() {
getValue();
getSquare();
}
function getValue() {
var a = prompt("Number please")
}
function getSquare() {
var b = Math.pow(a)
document.write(b)
}
start()
This assignment doesn't have to be working with any HTML tags. I've only got the prompt box to work, nothing else does though. Am I using variables in a way that can't be used?
You were close. But it seems that you don't understand scoping and how exactly to use the pow function.
Math.pow:
Math.pow takes two parameters, the base and the exponent. In your example, you only provide the base. That will cause problems as the function will return the value undefined and set it to b. This is how it should have looked (if you wanted to square it):
Math.pow(a, 2);
Scoping:
Every function has it's own scope. You can access other variables and functions created outside the function from within the function. But you cannot access functions and variables created inside another function. Take the following example:
var c = 5;
function foo() { // we have our own scope
var a = c; // Okay
}
var b = a; // NOT okay. a is gone after the function exits.
We could say that a function is private. The only exception is that we can return a value from a function. We return values using the return keyword. The expression next to it is the return-value of the function:
function foo() {
return 5;
}
var a = foo(); // a === 5
foo() not only calls the function, but returns its return-value. A function with no return-value specified has a return value of undefined. Anyway, in your example you do this:
function getValue() {
var a = prompt("Number please")
}
and access it like this:
// ...
var b = Math.pow(a)
Do you see the error now? a is defined in the function, so it can't be accessed outside of it.
This should be the revised code (Note: always use semicolons. I included them in for you where necessary):
function start() {
getSquare();
}
function getValue() {
var a = prompt("Number please");
return a;
}
function getSquare() {
var b = Math.pow(getValue(), 2); // getValue() -> a -> prompt(...)
document.write(b);
}
start();
As this is an homerwork, I won't give you direct answer, but here's some clue.
In javascript variables are functions scoped. That mean that var a inside getValue is only available in there.
You can return a value from a function.
Functions are first class object in javascript, so you can pass them as parameter to other function and finally call them inside that function.
Am I using variables in a way that can't be used?
Yes, that's where your problem lies. Variables in most programming languages have a scope that determines where they're available. In your case, a and b are local variables of the functions getValue() and makeSquare() respectively. This means they're not available outside the function they're declared in.
Generally speaking, this is a good thing. You should use restricted scopes for your variables to make the "flow" of data through your program clearer. Use return values and parameters to pass data between functions instead of making your variables global:
function start() {
var a = getValue();
makeSquare(a);
}
// Return a value entered by the user
function getValue() {
return prompt("Number please")
}
// Write the square of the `a` parameter into the document
function makeSquare(a) {
var b = Math.pow(a)
document.write(b)
}
Your getValue() needs to return the value, so that you then can pass it to the getSquare() function.
In my opinion, you should always end each line with ;
You will probably need to parse the user input into a number. For that you can use parseFloat(string).
Math.pow takes two arguments, so to get the square, you would have to pass 2 as a second argument when calling it.
I edited your code with some clarifying comments:
function start() {
// Catch the value returned by the function
var value = getValue();
// Pass the returned value to the square-function
getSquare(value);
}
function getValue() {
// Parse the user input into a number, and return it
return parseFloat(prompt("Number please"));
}
// Let the square-function take the user input as an argument
function getSquare(a) {
// Math.pow takes a second argument, which is a number that specifies a power
var b = Math.pow(a, 2);
document.write(b);
}
start();
Another, less good way
In JavaScript, variable-scoping is based on functions. If a variable is declared using the var keyword, it is only available to that function, and its child-functions. If it is declared without the var keyword, or declared outside any function, it becomes a global variable, which will be accessible by any code run on that page.
That said, you could get rid of the var keyword inside the getValue() function, which would make the variable a global. You could then access it from within getSquare() the way you tried in your example.
This is generally not a good idea though, since you would "pollute" the global namespace, and you would be running the risk that you accidentally have another script using a global variable with the same name, which would cause all kinds of trouble, when the scripts start to work with the same variable.
You can try this.
<script type="type/javascript">
function start(){
makeSquare(getvalue());
}
function getvalue(){
return prompt("enter a number");
}
function makeSquare(a){
var result=Math.pow(a,2);
alert(result);
}
start();
</script>

Categories