I originally come from the Java Programming language, and I was just wondering why it is possible in javascript to pass a callback function as a variable or plain object (without parameters) to another function, and then use this callback function inside of another function but this time with parameters to pass.
And how exactly is this callback returning my user object, as I did not specify a return function inside callback(user), or specify any function body at all for my callback. Is this done inside the setTimeout(()...) function as the timeoutHandler implementation is implicitly returning something?
var getUser = (id,callback) => {
var user = {
id: id,
name: 'Vikram'
};
setTimeout(() => {
callback(user);
},3000);
};
getUser(31, (userObject) => {
console.log(userObject);
});
I see two questions here:
why it is possible in javascript to pass a callback function as a variable or plain object (without parameters) to another function.
Because functions are first-class objects, we can pass a function as an argument in another function and later execute that passed-in function or even return it to be executed later.
Read more here: https://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/
Below shows functions are just objects as well:
function hello() {
return 'hello';
}
hello.other = 'world';
console.log(hello() + ', ' + hello.other);
how exactly is this callback returning my user object, as I did not specify a return function inside callback(user), or specify any function body at all for my callback.
setTimeout(()...) function is not implicitly returning anything, it just registers a function, that would execute later. When the function registered by the setTimeout triggers, it invokes the callback(user) and that resolves getUser registered function which logs to the console. Remember callbacks are asynchronous.
Functions have implicit returns if not specified, which returns undefined, meaning you did not explicitly return.
Below shows an example:
function hello() {
console.log('Hello, World');
}
console.log(hello()); // undefined.
function hi() {
return 'Hi, World';
}
console.log(hi()); // Hi, World.
The function i.e callback is passed as reference here. So you can pass it as much you want, when you call it then you can pass on the arguments and it will refer to original function.
And also it's not returning the user object, it's just consoling out the user object. As you have not used any return it will return undefined. Try consoling the callback fn return out.
var getUser = (id,callback) => {
var user = {
id: id,
name: 'Vikram'
};
setTimeout(() => {
console.log(callback(user), 'return value of callback');
},3000);
};
In javascript function is a object.
It behaves like function only with ()
So you can pass function to another function or variable as value.
Some functions in javascript are asynchronous.
setTimeout is such async function. It means callback function will be run after a time.
What's happening:
//assign anonymous function to variable
// until function without () it only a object
var getUser = (id,callback) => {
//set up params
var user = {
id: id,
name: 'Vikram'
};
// setup asynchronous function setTimeout
setTimeout(() => {
// run callback with params when time would done
callback(user);
},3000);
};
// call function which contains in getUser-variable and pass 2 params: int and callback-function
getUser(31, (userObject) => {
console.log(userObject);
});
Related
I wonder why this simple callback function (setTimout) gets called even though I didn't invoke but just assigned it.
In this code, I assinged setTimeout function to variable foo.
So I believe a returned value should be stored in variable foo
And It doesn't need to be executed and print 'hello' because I didn't call that function.
But why It gets called and print 'hello'?? What if I just want to assign and store it to variable??
Also How this function can be a number type and returned value is 2 ??
const foo = setTimeout(() => console.log('hello'), 2000);
// hello ( after 2 seconds )
console.log(typeof foo);
// number
console.log(foo);
// 2
Thanks in advance
To declare it a function to be called later:
const foo = function () {
setTimeout(() => console.log('hello'), 2000);
}
The return value of setTimeout is an integer Id for the timeout that can be used later with clearTimeout();
e.g.
var t = setTimeout(() => console.log('hello'), 2000);
// clear the time out
clearTimeout(t);
setTimeout invokes it. That's why it's called a callback. Another more common word for "invoke" is "call" so a callback is basically an invokeback: someone will invoke your code later.
Here's an example of code that accept a callback:
function foo (cb) {
// this function prints "foo" if callback returns true
if (cb()) { // foo() invoking cb()!
console.log('foo');
}
}
As you can see, the programmer who writes the function is the one who invokes/calls your function. You just need to define the function that they are going to call:
foo(function() { return true })
You just invoked the function with two parameters and stored the return result of setTimeout
const foo = setTimeout(() => console.log('hello'), 2000);//
Example:
I have a function setTimeout1
function setTimeout1(parm1, parm2){
// do somthing
return "Invoked";
}
const foo = setTimeout1(() => console.log('hello'), 2000);
I'm trying to access arguments from the function that is being passed as a parameter to make sure to pass those through, however I'm getting the error:
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
How can I get the arguments for func so that I can pass the message through when calling it?
UPDATE: maybe a better question is why can't I log func.arguments?
function a(func){
console.log(func.arguments)
return function(){
func.apply(null, func.arguments);
}
}
function log(message){
console.log(message)
}
a(log.bind('hello'))()
It can be done but its not pretty. you have to return an object with the parameters you want from the function you are passing
function a(func){
console.log(func.arguments)
//you dont actually need this since you have already called the function before passing
//return function(){
// func.apply(null, func.arguments);
//}
}
function log(message){
console.log(message);
return {
arguments : arguments //store the arguments and return them
};
}
//you not actually passing the function here (the way you have it written)
//you are calling it and returning its value
//we return { arguments: arguments } so the "a" function can retrieve its properties.
a(log("hello"));
I guess what you're trying to do is to intercept a function with a "logging" function.
If so, there is a different approach, using ES6 rest params --
let withLog = func => (...args) => {
console.log(...args);
return func(...args);
};
let add = (x, y) => x + y;
withLog(add)(2, 3); // outputs '2 3', returns 5
I am using the http module in node.js to read from url. The http.get function has this signature:
http.get(options[, callback])
The callback function takes a single argument, res. What can I do if I want to use extra objects/functions inside the callback? I can think of inlining the get call like so:
outerFunction = function(xyz) {
http.get(options, (res) => {
// do stuff with xyz here
xyz(res.blah);
}
});
But if my callback gets long I want to declare it upfront somewhere:
myCallback = function(xyz) {
return function(r) { xyz(r.blah); };
}
And invoke myCallback like so:
outerFunction = function(xyz) {
http.get(options, (res) => {
myCallback(xyz)(res);
});
}
But that seems super clumsy and only to get around the 1-arg callback restriction.
Are there better ways? Thanks!
you can use this code please,because myCallback return a function,then after get the resource,http will pass the res into xyz automatically.
outerFunction = function(xyz) {
http.get(options,myCallback(xyz));
}
You could use the arguments object.
The arguments object is a local variable available within all
functions. You can refer to a function's arguments within the function
by using the arguments object. This object contains an entry for each
argument passed to the function, the first entry's index starting at
0.
Quick example:
function test1234(a){
var args = arguments;
console.log(args); // prints -> 0: "a", 1: "b"
}
test1234('a', 'b');
I have got this code which register a callback method.
function BaseClass() {
var context = this;
(function initialize() {
context.registerField(context.Name, function updateValues(Name, value) {
context.Value = value;
});
})();
}
This is how the callback methods are being called.
updateValues.call(null, names, values);
The issue is the registerfield() is called multiple times with different context.
When the call back are being called they are not getting executed on correct context. How can I invoke the callback on correct objects?
updateValues.call(null, names, values);
I see a lot of javascript code that passes a function as a parameter that returns an anonymous object.
myFunction(function() {
return {
foo: 'bar'
};
});
What is the advantage or the purpose of using this instead of simply passing directly an anonymous object?
myFunction({
foo: 'bar'
});
The difference is that if you alter the argument passed in your second code snippet, there is no way to get the original argument again.
If you pass an function instead you can call the function more than once and get always the same argument back. (if the function is implemented this way)
Furthermore if you use a function you can do additional stuff like logging how often your function / argument was called or so on. So using a function adds more flexibility for the user of the function.
For the developer of the function on the other hand accepting a function as argument can cause the tiny problem that a function doesn´t have to return the same value every time you call it - myFunc() == myFunc() COULD return false, therefore i would not recommend handing over a function if it is supposed to JUST return an argument.
Backbone uses have a lot of places where they will initialize the function if passed to get the value, eg.
Backbone.Model.extend({
url: function() { return 'myurl.aspx'; }
});
// VS
Backbone.Model.extend({
url: 'myurl.aspx'
});
This is clever if you will have to make some calculation / run some conditions before you'ill know that the url is.
Backbone.Model.extend({
url: function() {
if ( this.get('name') ) {
return 'service1.aspx';
}
else {
return 'service2.aspx';
}
}
});
Your first example sends an anonymous function as the first argument to myFunction while the second example sends an object as the first argument.
myFunction(function() {
return {
foo: 'bar'
};
}); // function() {...}
myFunction({
foo: 'bar'
}); // {foo: 'bar'}
function myFunction(what) {
console.log(what);
}
If you are talking about closures, the main difference is that you can have private variables inside closures:
var setGet = (function() {
var v = null;
return {
get: function() { return v; },
get: function(val) { v=val; },
};
});
// VS:
var setGet = {
v: null,
get: function() { return this.v; },
get: function(val) { this.v; },
};
In the first example you can't access the variable v without using .get/.set on setGet while in the 2. example i can simple change it by setting setGet.v = 'new_val';
In the first example You are passing a callback function.
When we pass a callback function as an argument to another function,
we are only passing the function definition. We are not executing the function
in the parameter.
And since the containing function has the callback function in its parameter as a function definition, it can execute the callback anytime. This allows us to execute the callback functions at any point in the containing function.
A simple example for this is jQuery click binding :
/The anonymous function is not being executed there in the parameter.
//The anonymous function is a callback function
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
But in the second example you are simply passing an object to the called function.
Use this link to get more details about Callback functions. Enjoy :)
I think, it really depends where you saw the code being used.
In this case, myFunction seems to require you to pass a function rather than an Object.
But in general, Consider this
myFunction(function() {
var a = "bar";
return {
foo: a
};
});
and this:
var a = "bar"
myFunction({
foo: a
});
In the second case, anyone outside is able to access a. But in first case, a becomes similar to a private variable which is exposed as public by the function. So you might observe this in places where people wish to follow OOP concepts in the otherwise classless JS.
Another case is where you require a callback function or some function that is to be called later. So if the data is to be preserved until a certain something is over you can make it available as the return value of a function, rather than storing it globally...