Why can't you call functions declared inside parenthesis? - javascript

As far as I can tell, JS is function scoped and not block scoped, meaning objects declared inside (parenthesis) do not create a different execution context. However:
$('#firstBtn').click(function first() {
console.log("first activated");
});
$('#secondBtn').click(function() {
console.log("second activated");
first();
});
Returns Reference Error function is undefined. The function first is being declared inside a parenthesis, so technically it should be available to other functions that call it from the scope it was declared at.
But this works:
var callDat = $('#firstBtn').click(function first() {
console.log("first activated");
});
$('#secondBtn').click(function() {
console.log("second activated");
callDat.first();
});
My assumption is that since objects are functions, declaring a function inside an object can count as declared inside a different function scope even without curly braces. I however wish for a definitive answer on this.

In your second example, the first you're getting is not the one you've declared above - its the jQuery.first method available to all jQuery objects.
This is checkable - clicking "First" and then "Second" below does not output "first activated" from a click to the second button.
var callDat = $('#firstBtn').click(function first() {
console.log("first activated");
});
$('#secondBtn').click(function() {
console.log("second activated");
callDat.first();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="firstBtn">First</button>
<button id="secondBtn">Second</button>

Returns Reference Error function is undefined. The function first is being declared inside a parenthesis, so technically it should be available to other functions that call it from the scope it was declared at.
No. Function declarations create a variable in the scope they are declared with which has the same name as the function. Function expressions do not, even if they are named function expressions. (Named function expressions to create a variable of that name inside their own scope).
Further reading: JavaScript function declaration syntax: var fn = function() {} vs function fn() {}
My assumption is that since objects are functions,
Functions are objects. The reverse is not necessarily true.
declaring a function inside an object can count as declared inside a different function scope even without curly braces
No, it can't.

In first example you actually do create a scope - this:
$('#firstBtn').click(function first() {
console.log("first activated");
});
is actually this:
(function first() {
console.log("first activated");
})
And as such is not available to other scopes
Now - if you'll declare it as such:
function first() {
console.log("first activated");
}
$('#firstBtn').click(first);
$('#secondBtn').click(function() {
console.log("second activated");
first();
});
you won't get the error

It's a "function literal" or "function expression" which only returns a function as a value, but does not define it in the surrounding function scope as a variable. It does, however, have its own scope. See my snippet below for something very interesting:
var counter = 0;
// function "b" is acting as a value to be given to "a"
var a = function b() {
alert(counter);
counter++;
// both "b" and "a" are accessible in here
if(counter < 3) b();
};
a(); // only a is accessible here
Because it's not obvious from the syntax, the form...
function func() { ... }
...may be replaced by the following to be more clear:
var func = function() { ... };

Related

Can functions access variables defined in its own parent function?

Mozilla's Developer Resource shows two contradicting explanation regarding the function scope.
Here
indicates that even though a "variable is defined in the same scope as the function calls", the code will throw an error because "it is not defined inside the function definitions".
Example)
function myBigFunction() {
var myValue;
subFunction1();
}
function subFunction1() {
console.log(myValue);
} //this will show a reference error
However, here indicates that a "function defined inside another function can also access all variables defined in its parent function and any other variable to which the parent function has access".
Example)
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + ' scored ' + (num1 + num2);
}
return add();
} //this is ok
In your first example
function myBigFunction() {
var myValue;
subFunction1();
}
function subFunction1() {
console.log(myValue);
} //this will show a reference error
here myValue is included in a function myBigFunction() so it has a block scope.
Block scope means any code within that block (here function defines the block) can use that variable if function contain another function(function definition) and inner function using that variable then it will be passed in a closure to inner function. 2nd scenario exactly same what I explained here.
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + ' scored ' + (num1 + num2);
}
return add();
} //this is ok
In above example num1 and num2 are declared in function getScore(), and it has inner function add() since add function using num1 and num2 it will be passed as closure to add() function and there won't be any error while accessing those variables.
but in first example the variable is accessed out of scope and as the variable accessed outside of that function it won't be accessible and it will throw reference error.
I hope the explanation clear your understanding. to understand it thoroughly go through JavaScript scope and closure concept.
The reason why the first example fails and the second 'works' has to do with scope and closure. You can think of a function's 'curly braces' as the enclosure around its scope - or sphere of influence.
The first example fails because myBigFunction()'s variable is not accessible to subFunction1()'s scope. myBigFunction() also doesn't wrap subFunction1() which would provide a closure. Check out closures here.
However, add() is declared within the scope of the getScore() function. getScore() 'wraps' add() - providing a closure so that add() has access to variables within getScore()'s scope.
Use the this keyword to get parent variable i.e.
var bar = function () {
this.foo = "example";//the only catch is you have to have the this key word when defining the term.
var subfunction = function () {
this.foo = "This an example!";
}
}
(Hope this helps!)

JavaScript Inner Functions & 'this'

In my understanding, it is not until an object invokes a Function that this is actually assigned a value. And the value it is assigned is based exclusively on the object that invokes the Function.
Also, the scope chain rule in JS is LEG.
So, in (strict mode):
function one () {
var a = 2;
function two () {
console.log(a)};
two()
}
one() // output 2
But:
function one () {
var a = 2;
function two () {
console.log(this.a)};
two()
}
one() //output undefined
It was my understandig functions were objects, and in the previous invokation the function object one would be the making the call of two, which translates this.a into one.a. Obviously that is not the case.
Also:
function one () {
var a = 2}
console.log(one.a) //outputs undefined
Any clarification about what is happening would be very appreciated.
Thanks
function one () {
var a = 2;
function two () {
console.log(this.a)};
two()
}
one() //output undefined
Here you are calling both one and two as functions on their own, not as properties of some object (e.g. someObject.one()). This means that this will refer to the global scope (or to undefined if the code is in strict mode). The a property of your global scope is undefined, so that's why you see undefined. Calling two() inside of one() doesn't make it so that this refers to one.
function one () {
var a = 2}
console.log(one.a) //outputs undefined
a is not a property of one. It is a variable inside it. A property of one would look like this.
function one() {
}
one.a = 7;
console.log(one.a);
I think you are treating a regular function as a class object. You only call one() but you do not actually instantiate a new One() object.
Scope and Context are different concepts. Within a JS-Function scope one can address any value that either got assigned inside a function or any value that got assigned outside such a function as long as this function itself is a member of the outer scope. In addition, as long as a function does not create a closure, scope gets created just at a function's call time. Context is addressable too. But unlike scope, context gets evaluated at a functions call time. Thus this is just a placeholder for context that can vary from one time calling a function to another.
function contextAwareMethod(injectedValue) {
"use strict";
var
context = this, // dynamically evaluated.
innerScopeValue = "created at a functions call time";
console.log('dynamically evaluated context : ', context);
console.log('this.contextValue : ', (context && context.value));
console.log('innerScopeValue : ', innerScopeValue);
console.log('injectedValue : ', injectedValue);
}
console.log('"case A"');
contextAwareMethod('argument A');
console.log('\n');
console.log('"case B"');
contextAwareMethod.call({ value: "conext B"});
console.log('\n');
console.log('"case C"');
contextAwareMethod.call({ value: "conext C"}, 'argument C');
console.log('\n');
.as-console-wrapper { max-height: 100%!important; top: 0; }

Simultaneously Declaring Variables and Functions in JavaScript

Can anyone explain why
function x() {
console.log("Hello!");
}
var a = x;
a();
x();
produces
Hello!
Hello!
but this
var a = function x() {
console.log("Hello!");
}
a();
x();
throws an error when you try to call function x? Is the second x function not considered a hoisted function? I tried this in both nodejs and a browser.
What you have in the second example is what's called a named function expression.
Its name is not added to the containing scope, but is accessible within the scope of the function itself:
var a = function x() {
alert(x);
};
a();
This is useful in writing recursive functions or functions that otherwise reference themselves, as it ensures that the name won't get clobbered due to anything that happens outside the function's scope.
It also allows you to create self-referencing functions in places where you can't use a function declaration, such as in an object literal:
var myFavoriteFunctions = {
factorial: function f(n) {
return n === 1 ? 1 : n * f(n);
},
identity: function (v) { return v; }
};
console.log(myFavoriteFunctions.factorial(10));
Your first example is a function statement, which declares a name in its containing scope.
Your second example is a named function expression, which does not.
For more information, see here.

Using closures in Javascript

I have come across this javascript code.
var digit_name = function() {
var names = ['zero', 'one','two'];
return function(n) {
return names[n];
};
}();
alert(digit_name(1));
The output is one. I understand that the inner function is being assigned to the variable digit_name. What is the need for adding parentheses in the 6th line after the code of outer function. Can anyone tell what exactly is going on?
The added parentheses makes the outer function execute, if you omit it it will assign outer function to your digit_name instead of the inner function.
The ending () you see make that outer function execute immediately. So digit_name ends up storing the resulting inner function, as opposed to a pointer to the outer function.
For more information see: What is the purpose of a self executing function in javascript?
Let's give some names to these functions to better understand what's going on:
var digit_name = function outer() {
var names = ['zero', 'one','two'];
return function inner(n) {
return names[n];
};
}();
alert(digit_name(1));
So, there are two functions at play here: inner and outer. You're defining a function called outer, whose purpose is to create a closure scope capturing the names array, and defining and returning another function that has access to this closure. The parentheses at line 6 mean call the function, so the value that gets assigned to the digit_names variable isn't the outer function, but the inner one.
var digit_name = function() {...}; => digit_name is a function
var digit_name = function() {...}(); => digit_name is an object returned by the function
var digit_name = function() { // Create outer function
var names = ['zero', 'one','two']; // Define names array, this is done when the outer function is ran
return function(n) { // Return the new inner function, which gets assigned to digit_name
return names[n];
};
}(); // Execute the outer function once, so that the return value (the inner function) gets assigned to digit_name
There are two very quick processes here.
If we were to write this:
function makeDigitReader () { var names; return function (n) { return names[n]; }; }
var myDigitReader = makeDigitReader();
You would correctly guess that myDigitReader would be given the inner function.
What they're doing is skipping a step.
By adding the parentheses, what they're doing is firing the function the instant that it's defined.
So you're getting this happening:
var myDigitReader = function () {
var names = [...];
return function (n) { return names[n]; };
};
myDigitReader = myDigitReader();
See what's happened?
You've returned the inner function as the new value to what used to be the outer function.
So the outer function doesn't exist anymore, but the inner function still has access to the names array.
You can return an object instead of a function, as well.
And those object properties/functions would have access to what was initially inside of the function, as well.
Normally, you will either see these immediately-invoking functions wrapped in parentheses var myClosure = (function() { return {}; }());.
If you intend to run one without assigning its return to a value, then you need to put it in parentheses, or add some sort of operand to the front of it, to make the compiler evaluate it.
!function () { doStuffImmediately(); }(); // does stuff right away
function () { doStuffImmediately(); }(); // ***ERROR*** it's an unnamed function
Hope that answers all of the questions you might have.

JavaScript Nested function

I got a piece of code for javascript which I just do not understand:
function dmy(d) {
function pad2(n) {
return (n < 10) ? '0' + n : n;
}
return pad2(d.getUTCDate()) + '/' +
pad2(d.getUTCMonth() + 1) + '/' +
d.getUTCFullYear();
}
function outerFunc(base) {
var punc = "!";
//inner function
function returnString(ext) {
return base + ext + punc;
}
return returnString;
}
How can a function be defined within another function? Can we call pad2() from outside of my() function?
Please put some light on it. Thanks
Functions are another type of variable in JavaScript (with some nuances of course). Creating a function within another function changes the scope of the function in the same way it would change the scope of a variable. This is especially important for use with closures to reduce total global namespace pollution.
The functions defined within another function won't be accessible outside the function unless they have been attached to an object that is accessible outside the function:
function foo(doBar)
{
function bar()
{
console.log( 'bar' );
}
function baz()
{
console.log( 'baz' );
}
window.baz = baz;
if ( doBar ) bar();
}
In this example, the baz function will be available for use after the foo function has been run, as it's overridden window.baz. The bar function will not be available to any context other than scopes contained within the foo function.
as a different example:
function Fizz(qux)
{
this.buzz = function(){
console.log( qux );
};
}
The Fizz function is designed as a constructor so that, when run, it assigns a buzz function to the newly created object. That is, you'd use it like this:
const obj = new Fizz();
obj.buzz();
or more concisely (if you don't need to keep the object after calling buzz):
new Fizz().buzz();
It is called closure.
Basically, the function defined within other function is accessible only within this function. But may be passed as a result and then this result may be called.
It is a very powerful feature. You can see more explanation here:
javascript_closures_for_dummies.html mirror on Archive.org
function x() {}
is equivalent (or very similar) to
var x = function() {}
unless I'm mistaken.
So there is nothing funny going on.
Function-instantiation is allowed inside and outside of functions. Inside those functions, just like variables, the nested functions are local and therefore cannot be obtained from the outside scope.
function foo() {
function bar() {
return 1;
}
return bar();
}
foo manipulates bar within itself. bar cannot be touched from the outer scope unless it is defined in the outer scope.
So this will not work:
function foo() {
function bar() {
return 1;
}
}
bar(); // throws error: bar is not defined
When you declare a function within a function, the inner functions are only available in the scope in which they are declared, or in your case, the pad2 can only be called in the dmy scope.
All the variables existing in dmy are visible in pad2, but it doesn't happen the other way around :D
It's perfectly normal in JavaScript (and many languages) to have functions inside functions.
Take the time to learn the language, don't use it on the basis that it's similar to what you already know. I'd suggest watching Douglas Crockford's series of YUI presentations on JavaScript, with special focus on Act III: Function the Ultimate (link to video download, slides, and transcript)
function foo() {
function bar() {
return 1;
}
}
bar();
Will throw an error.
Since bar is defined inside foo, bar will only be accessible inside foo.
To use bar you need to run it inside foo.
function foo() {
function bar() {
return 1;
}
bar();
}
Nested functions can be the basis for writing a modular group of related functions, kind of halfway to full object-oriented programming (static classes only).
Here is an example of such a group of functions, in this case to convert a value to a JSON string or a JSON string to a value.
Notice how the inner functions are grouped into an Object inside an outer function, and how the Object is then stored into a group name. This is the only name directly visible from outside the group. To reach any contained function from outside, you just write the group name, a period, then the function name. To reach a contained function from inside, you can use the same notation, or 'this', a period, then the function name.
//--------------------------------------------------------------------//
// Module J:
// Convert from and to JSON strings
//--------------------------------------------------------------------//
const J=NewJ();
function NewJ()
{
const mod=
{
From:(str)=>
{
return JSON.parse(str);
}, // From
To:(val)=>
{
return JSON.stringify(val,null,3);
} // To
}; // mod
return mod;
} // NewJ
//--------------------------------------------------------------------//
// End Module J
//--------------------------------------------------------------------//
Here's a test:
console.log(J.To({A:'a'}));
Console output:
{
"A": "a"
}

Categories

Resources