in the following code
const express = require('express');
const app = express()
app.use(express.static('public'));
express is a function so how it call "express.static('public')" method on it? is it possible in JavaScript to call a function which is inside a function
A functions is not only a first class function, but also a first class object and can contain properties.
function foo() {}
foo.bar = function () { console.log('i am bar'); };
foo.bar();
You can attach a function as member data to another function (which is what is done in your example).
const express = () => {};
express.static = argument => console.log('argument');
express.static('public'); # console >>> 'public'
However, you cannot readily access a variable that is defined in a function body.
const express = () => {
const static = argument => console.log('argument');
};
express.static('public'); # console >>> Error: undefined in not a function
There is a signifiant difference between member data attached to a function (the first example) and the closure that wraps the body of the function (the second example).
So, to answer your question "is it possible in JavaScript to call a function which is inside a function?" No, this is not readily possible with the important note that this is not what is being done in your example.
Actually, it is possible to call a function inside another function in javaScript.
So it depends on the condition, Callback is widely used in js
(A callback is a function that is to be executed after another
function has finished executing)
function doHomework(subject, callback) {
alert(`Starting my ${subject} homework.`);
callback();
}
function alertFinished(){
alert('Finished my homework');
}
doHomework('math', alertFinished);
And the second example can be Closures
(A closure is a feature in JavaScript where an inner function has
access to the outer (enclosing) function's variables)
function outer() {
var b = 10;
function inner() {
var a = 20;
console.log(a+b);
}
return inner;
}
Related
I have two javascript modules. I need to pass a function argument to another file. But am getting reference error foo is not defined in line3. Please help.
1.test1.js
exports.foo= function foo(x){ //line1
// do something
}
test2 = require("test2") // line2
test2.bar(foo) //line3
2.test2.js
exports.bar= function bar(foo){
foo(123)
}
Problem is in line1 of test1.js:
exports.foo= function foo(x){
where function foo(x){... is a function expression.
Named function expressions do not create a function declaration of the same name, and the name supplied is only available inside the expression. (Possibly with the exception of some ancient versions of IE about which I care nothing)
You could either create foo as a function declaration and assign it:
function foo() { ... code }
exports.foo = foo;
or call it in line 3 as test2.bar(exports.foo)
use the following approach
module.exports = function foo(x){
//implementation
}
You should assign the function to a variable.
const foo = function foo(x){
// do something
}
test2 = require("./test2")
test2.bar(foo)
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);
});
Let's say I have a function myFunction which in it's body uses results of other function otherFunction and those results are constant per every invocation.
function myFunction() {
doSomething(otherFunction());
}
In the past I used IIFE-s to invoke otherFunction only once and so optimize the code:
var myFunction = (function() {
let otherFunctionResult = otherFunction();
return function() {
doSomething(otherFunctionResult);
};
}());
I wonder if ES6 const keyword would achieve the same result without using IIFE:
function myFunction() {
const OTHER_FUNCTION_RESULT = otherFunction();
doSomething(OTHER_FUNCTION_RESULT);
}
Can I expect const to be optimized so that otherFunction is invoked only once? That would greatly simplify the code.
The fact that OTHER_FUNCTION_RESULT is declared as const doesn't mean it's only ever called once:
function callOften(){
const test = init(); // This is a `const`, but does it get called more often?
}
function init(){
console.log('Init Called');
return 1;
}
callOften();
callOften();
callOften();
Basically, your IIFE is one way to do what you want.
Yes, you don't need IIFEs any more in ES6. However, you seem to confuse const with what static does in other languages. You still need to initialise it outside of the function if you want to invoke otherFunction only once. It would look like this:
var myFunction;
{ // block scope!
let otherFunctionResult = otherFunction(); // `const` works the same here
myFunction = function() {
doSomething(otherFunctionResult);
};
}
Admittedly, an IIFE is still nicer to read if your module has a result (here: the function) that is supposed to be stored in a non-local variable.
I have this code and wondering how can we access properties and method of IIFE
var app = (function () {
function app() {
this.name = 'fasf';
}
app.prototype.greeting = function () {
this.a = 'hello world';
console.log(name);
window.alert('hello world');
};
app.prototype.sayhello = function () {
var j = 't';
console.log(this.a);
};
return app;
}());
also about this piece of code
var t = (function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
})();
With the code you have, you can just do this:
// create an instance of the app object
var a = new app();
// call methods on it
a.greeting();
a.sayhello();
Your IIFE returns the internal app constructor function and then assigns that to a variable named app. So you can then do new app() to create an instance of that object. Once you create an instance of that object, you can then call any of the methods on the prototype.
In your second IIFE, nothing is returned from the IIFE so t is undefined.
The IIFE itself does not have properties and methods. That's just an immediately invoked function expression. In your first one, it returns a constructor function which is then assigned to a variable so that variable can be used to create objects with that constructor function. There are no properties or methods of the IIFE itself.
The way the IIFE pattern works is that you use local variables for the stuff you want to keep private. Local variables are are only visible inside the function they were defined in they cannot be read or written from anywhere else in the program.
If you want to expose things inside the IIFE outside the IIFE one way to do it is via the return value of the immediately-invoked function:
var stuff = (function(){
// These variables and functions are not
// visible from the outside:
var myvar1 = "Hello";
var myvar2 = "World";
var func1(){
return myvar1 + " " + myvar2;
}
// But we can return a record that contains a
// reference to our private functions, making them
// visible outside this block.
return {
thefunc: func1
}
}());
//Now we can call the "thefunc" function we exported
console.log( stuff.thefunc() );
I made sure to not repeat any variable names to avoid confusion.
In your first example, there isn't much of a point to using the IIFE pattern since there are no local variables that you are making private. You could have just defined the app function outside the IIFE and it would have worked the same.
The second case could have been written more clearly by putting the function in a separate line:
function greet(name){
name = name || 'enter your name'
console.log('Hello ' + name);
}
var t = greet();
Not only is it a bit weird to immediately invoke a named function but in your particular example, the "default argument value" pattern suggests that this function was designed to be called multiple times, sometimes passing the "name" argument and sometimes not passing it (in which case it defaults to the "enter your name" string.
When using IIFE pattern (closure) you usually keep local variables and function private as properly mentions by hugomg's answer.
In case you need to selectively make public some specific property you could consider using "The Revealing Module Pattern" instead, more info here.
Below a simple example showing this pattern:
var app = (function () {
var privateVar = 'hello world';
function sayhelloPrivate() {
console.log(privateVar);
}
function sayhelloPublic() {
console.log(privateVar);
}
// reveal public pointers to
// private functions and properties
return {
sayhello : sayhelloPublic
};
})();
app.sayhello();
//app.sayhelloPrivate(); this will not work as function is private and not visible outside module
What's the difference between:
var NodestrapGenerator = module.exports = function NodestrapGenerator() {
yeoman.generators.Base.apply(this, arguments);
// more code here
};
and:
var NodestrapGenerator = module.exports = function() {
yeoman.generators.Base.apply(this, arguments);
// more code here
};
I'm trying to write my yeoman-generator's index.js in coffeescript, but apparently the second snippet isn't the same because it's not working! Thanks!
var NodestrapGenerator = module.exports = function NodestrapGenerator() { ... };
This is a named function called "NodestrapGenerator", assigned to variable NodestrapGenerator.
var NodestrapGenerator = module.exports = function() { ... };
This is an unnamed function aka. anonymous function, which gets assigned to variable NodestrapGenerator.
In the end, they're both referencing the same function, so no difference which way you write it.
See this for more explanation: var functionName = function() {} vs function functionName() {}
As to why it's not working, its probably because the code is looking for the named function NodestrapGenerator to verify that it's the function it should be using, not some random anonymous function.
FYI, function has a property name which will get set to "NodestrapGenerator" in named function (first example), but will be empty string "" in anonymous function (second example). (See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/name)