In JavaScript, is there any mechanism that would make it possible to set a function return value without using the keyword "return"?
6 Answers
Of course you can. All the other answers talk about:
- Assigning a value to a variable in a parent scope.
- Assigning a value to a property of an object in a parent scope.
There is however a third method and this method is very powerful: CONTINUATIONS.
For a moment let's assume that return is a function. For example:
function add(a, b) {
return(a + b);
}
Now what if you didn't want to use return? We could do something like this:
function add(a, b, ret) {
ret(a);
}
To put it simply a continuation is a function which is used in place of a return statement. More formally:
A continuation is a function which is called by another function. The last thing the other function does is call the continuation. It doesn't do anything else after that.
Hence a continuation is like the functional equivalent of the return statement.
Continuations have a lot of advantages:
- You can pass multiple return values to the continuation.
- You can write functions recursively instead of iteratively.
- You can choose not to call the continuation (in which case you're changing the control flow).
- You can choose to call one of multiple continuations (like a
throwcontinuation).
However continuations have two main disadvantages:
- If you write programs in continuation passing style then you'll end up with a lot of nested functions.
- JavaScript doesn't have tail call elimination. Hence recursive functions increase the stack size.
For example:
function fib(n, k) {
switch (n) {
case 0: k(0); break;
case 1: k(1); break;
default:
fib(n - 1, function (x) {
fib(n - 2, function (y) {
k(x + y);
});
});
}
}
fib(20, console.log); // maximum recursion depth exceeded
You can use setTimeout to eliminate tail call recursion:
Function.prototype.async = function () {
return setTimeout.bind(null, this, 0).apply(null, arguments);
};
function fib(n, k) {
switch (n) {
case 0: k(0); break;
case 1: k(1); break;
default:
fib.async(n - 1, function (x) {
fib.async(n - 2, function (y) {
k(x + y);
});
});
}
}
fib(20, console.log); // 6765
You can use backcalls from LiveScript to make your code look better:
Function::async = -> setTimeout.bind(null, @, 0) ...
fib = (n, k) -->
| n == 0 => k 0
| n == 1 => k 1
| otherwise =>
x <- fib.async n - 1
y <- fib.async n - 2
k x + y
fib 20, alert # 6765
You can try it out for yourself on the http://livescript.net/ site. Just use a value smaller than 20. Preferably 10.
1 Comment
There is no other way to return a value, that's what return is for.
But since we have side effects, you can edit a variable in a wider scope like this:
var a = 5;
function setA(x)
{
a = x;
}
setA(6);
Alternatively you can pass an object to the function and by using pass by reference change variables in that object. This page details how that works.
As mentioned above, this is not the same as a result value, as the following will fail:
var newA = setA(a); // undefined instead of 5
Comments
My understanding is that you don't want to use return because you don't want to stop your function. So you can use promises to get a value from a function without stopping it:
const run = () => new Promise((resolve)=>{
const a = 1 + 1;
resolve(a);
console.log('next');
})
async function test(){
const neededResults = await run();
console.log(neededResults);
}
test()
1 Comment
using some global varible or if you want OOP concept then some class variable will be use and updates without return statement
var num1 = 5;
alert(num1);
function sum(a,b) {
num1 = a+b; // Function Without return statement
}
//Calling Function
sum(3,4);
alert(num1);
7 Comments
return and I don't see how that's a problem. Why do you want to "return" a value from a function without using return? What are you trying to do?The best (most readable/testable) way to create your functions is to have them receive what they need, and return what they should. However if you need to avoid returning for some reason there are several ways to do this:
Set a variable in scope
You could create a variable in a closure, then set the value in a function.
(function() {
var a = 12;
var fnc = function() {
a = 13;
}
fnc();
// value of a is now 13 as a is in scope for fnc
})();
Create a global object
You could create a global object and set an attribute on it:
window.app = window.app || {};
app.a = 12;
var b = function() {
app.a = 13;
}
b();
// the value of app.a is now 13 as app is in scope for fnc
var result = myFunc();won't work, this is not a return value.