Javascript - need explanation on the variable inside IIFE - javascript

I have this code - I just wonder why after I add 'var' to foo variable, it doesn't work (it shows me foo is undefined)... Can anyone help explain these two functions? Thanks!
window.onload = function() {
var test = foo().steps(2);
console.log(test);
}
(function() {
//if I remove var, then it prints out a function which is what I expected
var foo = function() {
var steps = 1;
function callMe(g) {
//do something else
console.log("hello" + g);
}
callMe.steps = function(x) {
//if no arguments then return the default value
if (!arguments.length) return steps;
console.log(arguments);
//otherwise assign the new value and attached the value to callMe
steps = x;
return callMe;
}
return callMe;
}
})();

adding var to foo makes foo a local variable inside the IIFE and thus you can't access it outside.

Related

how to call function inner function from outer one assigned to a variable

I have this function
var x = function outer() {
console.log('outer')
this.inner = function() {
console.log("inner");
}
}
The question is how can I call the inner function outside this scope? I tried x().inner() but it doesn't work
Your trying to use a type function as a Class
try this:
class Outer {
inner () {
console.log("inner");
}
}
console.log(new Outer.inner()) //output inner
here some ref https://www.w3schools.com/js/js_classes.asp
I can't return this from the outer function, can I access inner function from x variable? - Tarik Ziyad's (OP) comment
If you want to execute only the inner function, you might be for something like this then (or a prototype):
var outer = function () {
this.inner = function() {
return 'inner';
}
return 'outer';
}
outer.prototype.innerProto = function() {
return 'inner-proto';
}
var x = new outer;
console.log(x.inner());
console.log(x.innerProto());
Your outer function does not return a value.
What happens in your code is that, when you run x(), it will execute outer function, which is going to log something to console, declare this.inner and exit.
What you need to do is to return this at the end of outer function.
Like this:
var x = function outer() {
console.log('outer')
this.inner = function() {
console.log("inner");
}
return this;
}
Then you can do x().inner() and it will work perfectly!
in the way you do it.
this keyword is pointing to window Object so if you want to call inner you can just
use window.inner();
but if you want to use it as a method you must use new keyword.
new keyword create a new object and assine the this keyword to it so inner can be a method for something in my example.
function Outer() {
console.log('outer')
this.inner = function() {
console.log("inner");
}
}
var something = new Outer();
something.inner();

What is the function's return value?

Could you please tell me what is Menu in the return statement below (return Menu;) ? Is it a variable (which is not defined) or the name of the inner function ?
var Menu = (function () {
// A straightforward constructor.
function Menu(item_list, total_pages) {
// The this keyword is mandatory.
this.items = item_list;
this.pages = total_pages;
}
// Methods
Menu.prototype.list = function () {
console.log("Our menu for today:");
for (var i = 0; i < this.items.length; i++) {
console.log(this.items[i]);
}
};
return Menu;
}());
Is it a variable...?
Effectively. It comes from the function declaration:
function Menu(item_list, total_pages) {
// The this keyword is mandatory.
this.items = item_list;
this.pages = total_pages;
}
Function declarations create what the spec calls a "binding" in the current execution context for the scope. It's effectively a variable.
So return Menu; returns the Menu function reference out of the anonymous function, and the outer var Menu = ... assignment assigns it to the Menu variable in the containing scope.
Function declarations create a variable, in the scope of the function they are declared in, with a name that is the same as the name of the function itself.
So the return value is the function, which is the same as the value of the Menu variable.
function return_function() {
function foo() {
console.log(1);
}
console.log(foo);
var bar = foo;
foo = 2;
console.log(foo);
return bar;
}
var baz = return_function();
baz();

Execution order of simple function

I am a bit new to javascript, i was just trying the below snippet:
_getUniqueID = (function () {
var i = 1;
return function () {
return i++;
};
}());
s = _getUniqueID();
console.log(s); // 1
console.log(_getUniqueID()); // 2
I was under the impression that i would have to do s() to get 1 as the result and i was thinking that _getUniqueID() returns a function rather than execute the funtion inside it. Can somebody explain the exact execution of this function please ?
What you're seeing here is a combination of Javascript's notion of closure combined with the pattern of an immediately invoked function expression.
I'll try to illustrate what's happening as briefly as possible:
_getUniqueID = (function () {
var i = 1;
return function () {
return i++;
};
}()); <-- The () after the closing } invokes this function immediately.
_getUniqueID is assigned the return value of this immediately invoked function expression. What gets returned from the IIFE is a function with a closure that includes that variable i. i becomes something like a private field owned by the function that returns i++ whenever it's invoked.
s = _getUniqueID();
Here the returned function (the one with the body return i++;) gets invoked and s is assigned the return value of 1.
Hope that helps. If you're new to Javascript, you should read the book "Javascript, the Good Parts". It will explain all of this in more detail.
_getUniqueID = (function () {
var i = 1;
return function () {
return i++;
};
}());
s = _getUniqueID();
console.log(s); // 1
console.log(_getUniqueID()); // 1
when you do () it calls the function,
a- makes function recognize i as global for this function.
b- assigns function to _getUniqueID
you do s = _getUniqueID();,
a - it assigns s with return value of function in _getUniqueID that is 1 and makes i as 2
when you do _getUniqueID() again it will call the return function again
a- return 2 as the value and
b makes value of i as 3.
This is a pattern used in Javascript to encapsulate variables. The following functions equivalently:
var i = 1;
function increment() {
return i ++;
}
function getUniqueId() {
return increment();
}
But to avoid polluting the global scope with 3 names (i, increment and getUniqueId), you need to understand the following steps to refactor the above. What happens first is that the increment() function is declared locally, so it can make use of the local scope of the getUniqueId() function:
function getUniqueId() {
var i = 0;
var increment = function() {
return i ++;
};
return increment();
}
Now the increment function can be anonymized:
function getUniqueId() {
var i = 0;
return function() {
return i ++;
}();
}
Now the outer function declaration is rewritten as a local variable declaration, which, again, avoids polluting the global scope:
var getUniqueId = function() {
var i = 0;
return (function() {
return i ++;
})();
}
You need the parentheses to have the function declaration act as an inline expression the call operator (() can operate on.
As the execution order of the inner and the outer function now no longer make a difference (i.e. getting the inner generator function and calling it, or generate the number and returning that) you can rewrite the above as
var getUniqueId = (function() {
var i = 0;
return function() {
return i ++;
};
})();
The pattern is more or less modeled after Crockford's private pattern
_getUniqueID = (function () {
var i = 1;
return function () {
return i++;
};
}());
console.log(_getUniqueID()); // 1 , this surprised me initially , I was expecting a function definition to be printed or rather _getUniqueID()() to be called in this fashion for 1 to be printed
So the above snippet of code was really confusing me because I was't understanding that the above script works in the following manner, by the time the IFFE executes _getUniqueID is essentially just the following:
_getUniqueID = function () {
i = 1
return i++;
};
and hence,
_getUniqueID() // prints 1.
prints 1.
Note: please note that I understand how closures and IFFE's work.

Using Constructor variables during the instantiation

Is it possible, while creating an instance of an object, to check during the instantiation itself the type of the parameter passed to the constructor, and set one of the object's variable accordingly?
This is what I'm trying to do:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(this.num1); // logs "undefined" upon instantiation
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);
I want isValidNumber's value to be true or false according to the parameter passed to the constructor.
Your IIFE (Immediately-Invoked Function Expression) creates a new context, which means this doesn't point to your constructor anymore but to the Window object (unless you're using strict mode which would make it undefined). One possible solution is to execute this function with the right context:
this.isValidNumber = function() {
if (isNaN(this.num1)) {
return false;
} else {
return true;
}
}.call(this);
The much simpler solution is obviously:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = !isNaN(this.num1);
}
First of all, the code could (and probably should) be rewritten the following way:
function Test(num1) {
this.num1 = num1;
console.log(this.num1);
this.isValidNumber = !isNaN(this.num1);
}
As for the reason why your code is not working as expected – your self invoking function has its own this parameter which is unrelated to the this parameter within your constructor.
In this case the this parameter of your self invoking function references the global object. (In strict mode it would've been undefined)
If you really need to reference the this parameter of a containing function then there are several ways to achieve this, the simplest of which being:
function Test(num1) {
this.num1 = num1;
var self = this;
this.isValidNumber = (function() {
console.log(self.num1);
return !isNaN(self.num1));
}());
}
In your particular case you don't even need to capture it, and this would also achieve the same effect:
function Test(num1) {
this.num1 = num1;
this.isValidNumber = (function() {
console.log(num1);
return !isNaN(num1));
}());
}
But again, the self invoking function is simply not required here.
This in the inner function no longer references the parent object. A common way of storing the object reference is to create a 'self' variable and assign this to it when it's in the correct scope
function Test(num1) {
var self = this;
this.num1 = num1;
this.isValidNumber = (function() {
console.log(self.num1);
if (isNaN(self.num1)) {
return false;
} else {
return true;
}
}());
}
var testObj = new Test(5);

Javascript call nested function

I have the following piece of code:
function initValidation()
{
// irrelevant code here
function validate(_block){
// code here
}
}
Is there any way I can call the validate() function outside the initValidation() function? I've tried calling validate() but I think it's only visible inside the parent function.
function initValidation()
{
// irrelevant code here
function validate(_block){
console.log( "test", _block );
}
initValidation.validate = validate;
}
initValidation();
initValidation.validate( "hello" );
//test hello
Hope that you are looking for something like this
function initValidation()
{
// irrelevant code here
this.validate = function(_block){
// code here
}
}
var fCall = new initValidation()
fCall.validate(param);
This will work.
Hope this addresses your problem.
You can call validate from within initValidation. Like this.
function initValidation()
{
// irrelevant code here
function validate(_block){
// code here
}
return validate(someVar);
}
validate is not visible to anything outside of initValidation because of its scope.
Edit: Here's my suggestion of a solution.
(function() {
function validate(_block){
// code here
}
function initValidation()
{
// irrelevant code here
return validate(someVar);
}
function otherFunctions() {
// ...
}
// initValidation = function
}());
// initValidation = undefined
All of your functions will be hidden to anything outside the function wrapper but can all see each other.
This invocation will return function statement, which is function validate.
So you can invoke directly after the first invocation.
function initValidation() {
// irrelevant code here
return function validate(_block) {
// code here
}
}
initValidation()();
I know this is an old post but if you wish to create a set of instances that you wish to work with that reuse the code you could do something like this:
"use strict";
// this is derived from several posts here on SO and ultimately John Resig
function makeClassStrict() {
var isInternal, instance;
var constructor = function(args) {
if (this instanceof constructor) {
if (typeof this.init == "function") {
this.init.apply(this, isInternal ? args : arguments);
}
} else {
isInternal = true;
instance = new constructor(arguments);
isInternal = false;
return instance;
}
};
return constructor;
}
var MyClass = makeClassStrict();// create "class"
MyClass.prototype.init = function(employeeName, isWorking) {
var defaultName = 'notbob';
this.name = employeeName ? employeeName : defaultName;
this.working = !!isWorking;
this.internalValidate = function() {
return {
"check": this.working,
"who": this.name
};
};
};
MyClass.prototype.getName = function() {
return this.name
};
MyClass.prototype.protoValidate = function() {
return {
"check": this.working,
"who": this.name
};
};
var instanceBob = MyClass("Bob", true);// create instance
var instanceFred = MyClass("Fred", false);// create instance
var mything = instanceFred.internalValidate();// call instance function
console.log(mything.check + ":" + mything.who);
var myBobthing = instanceBob.protoValidate();
console.log(myBobthing.check + ":" + myBobthing.who);
I know this thread's been here for quite some time but I thought I'd also leave my 0.02$ on how to call inner functions from outside their scope (might benefit somebody).
Note that in any place, a better design decision should be taken into consideration rather than some hackish workaround which will bite you back later.
How about using function expressions instead of function statements and making use of the global scope.
var innerFn;
function outerFn() {
innerFn = function(number) {
return number ** 2;
}
}
outerFn();
console.log(innerFn(5));
// if there's more complex code around and you could write this defensively
if (typeof innerFn !== 'undefined') {
console.log(`we are squaring the number 5 and the result is: ${innerFn(5)}`);
} else {
console.log('function is undefined');
}
Or, you can make use of closures:
function outer() {
// initialize some parameters, do a bunch of stuff
let x = 5, y = 10;
function inner() {
// keeps references alive to all arguments and parameters in all scopes it references
return `The arithmetic mean of the 2 numbers is: ${(x + y) / 2}`;
}
return inner;
}
innerFn = outer(); // get a reference to the inner function which you can call from outside
console.log(innerFn());
Create a variable outside the parent function, then in the parent function store your required function in the variable.
Var Store;
Function blah() {
Function needed() {
#
}
Store = needed;
}
As a minor variation of Esailija's answer, I did this:
function createTree(somearg) {
function validate(_block) {
console.log( "test", _block );
}
if (somearg==="validate") { return validate; } // for addNodes
// normal invocation code here
validate(somearg);
}
function addNodes() {
const validate = createTree("validate");
//...
validate( "hello" );
}
createTree("create");
addNodes();
//validate("illegal");
so validate() is now perfectly shared between createTree() and addNodes(), and perfectly invisible to the outside world.
Should work.
function initValudation() {
validate();
function validate() {
}
}
Function definition:
function initValidation() {
// code here
function validate(_block){
// code here
console.log(_block);
}
return validate;
}
Call it as below:
initValidation()("hello");
function initValidation()
{
function validate(_block){
console.log(_block)
// code here
}
// you have to call nested function
validate("Its Work")
}
// call initValidation function
initValidation()

Categories