Javascript function & nested functions - javascript

Purpose: I need to call sub function within main one;
Function declaration:
var MainFunction = function () {
function NestedFunc1(){
console.warn("NestedFunc1");
};
function NestedFunc2(){
console.warn("NestedFunc2");
};
}
Functions call:
MainFunction.NestedFunc1();
MainFunction.NestedFunc2();
What am I doing wrong?
10x;

you can make it public via a property then
function MainFunction () {
this.nestedFunc1 = function(){
console.warn("NestedFunc1");
};
this.nestedFunc2 = function(){
console.warn("NestedFunc2");
};
}
now you can invoke this function outside by doing
var malObj = new MainFunction();
malObj.nestedFunc1();
However, if you want to still invoke it like MainFunction.NestedFunc1() then make it
var MainFunction = {
NestedFunc1:function (){
console.warn("NestedFunc1");
},
NestedFunc2:function (){
console.warn("NestedFunc2");
}
}

The issue is that both of those functions are isolated within a function scope. Think of them as private functions.
One (of many) solutions could be to define MainFunction as a plain ol' object that has some functions as attributes:
var MainFunction = {
NestedFunction1: function () { .. },
NestedFunction2: function () { .. }
};
Notice that a comma is needed to separate the functions because of the way we are defining them. You then just call
MainFunction.NestedFunction1();
Also note that this pattern is fine as long as you don't wish to have other "private" functions inside that object.

Related

Javascript: Encapsulation & Abstraction

I am writing an application code in javascript.
I just want an expect advice on how Encapsulation be achieved in JS,
The pattern which I wrote is something like,
var app = (function (window) {
// define variables here
// define functions here
return {
init: function () {},
plotGraph: function () {},
plotTable: function () {},
resizeHanlder: function () {},
initMenu: function () {},
attachEvent: function () {}
}
})(this);
Is there anything better than this.
Why I am doing this?
I really do not want to pollute global scope
What you are trying to make is called revealing module pattern. Here is one link on this topic:
https://carldanley.com/js-revealing-module-pattern/
Let's short analyse your code:
There will be only one global variable app. It get assigned the result of an anonymous functions, which is self-executed (we'll see that in the last line), also called Immediately-Invoked Function Expressin (IIFE).
var app = (function (window) {
The function returns an object which is assigned to the variable app
return {
init: init,
plotGraph: function () {},
plotTable: function () {},
resizeHanlder: function () {},
initMenu: function () {},
attachEvent: function () {}
}
The following code will never be executed, as the function already returned a value in the previous step.
function init() {}
And this here makes the function self-executable.
})(this);
Since your code has errors I would give you a simple example how to implement the revealing module pattern:
var hello = (function () {
var sayHello, makeGreeting;
sayHello = function () {
return 'Hello, ';
};
makeGreeting = function (name) {
console.log(sayHello() + name);
}
return {
makeGreeting : makeGreeting
};
})();
Now we have one object hello with one method makeGreeting. There is additional logic within which is not exposed to the end user, because he/she doesn't need to know it or isn't supposed to change those values.
Here is another example for this pattern from my GitHub:
https://github.com/cezar77/roman/blob/master/roman.js

Call a nested function within a prototype method

I'm trying to call a function nested within a prototype method. I get undefined when I try to reference this nested function. example -
testObj.prototype.funcA = function() {
var that = this;
that.funcB.subFuncA(); //call nested function within funcB - undefined
}
testObj.prototype.funcB = function() {
var subfuncA = function() {
//call this function from funcA
}
}
Thanks for any help provided.
subfuncA is locally scoped. It is not exposed outside funcB at all. This is (one way, sort of) how you create private functions in JS.
If you want subfuncA to be public, then stick it somewhere public.
testObj.prototype.funcA = function() {
var that = this;
that.funcB.subFuncA(); //call nested function within funcB - undefined
}
testObj.prototype.funcB = function() {
}
testObj.prototype.funcB.subfuncA = function () {
};

Javascript function undefined?

I am fairly new to javascript and jquery. I thought i had learned enough to do this, but apparently not. I think the code is fairly self explanatory.
The problem is that ArrowDir is apparently undefined. It looks defined to me, but I'm sure I'm missing something obvious.
function ArrowDir(){
var up = function(){
$("#arrow").attr('src','up_arrow.jpg');
};
var down = function(){
$("#arrow").attr('src','down_arrow.jpg');
};
}
$(function () {
if($("#toggle").onclick){
ArrowDir().down();
};
});
I've tried assigning the function as a variable, var ArrowDir = function(), but it doesn't seem to make a difference
You can't access the up and down values in the manner that you've written. You'd need to simply call down() from within the ArrowDir body, unless you've added those functions to the ArrowDir return value:
ArrowDir() {
var up = ...;
var down = ...;
return {
up: up,
down: down
};
}
Alternatively, if you're not using ArrowDir for anything other than encapsulating the up and down functions, you should just declare ArrowDir as an object, and call ArrowDir.up() and ArrowDir.down():
var ArrowDir = {
up: function () {
...
},
down: function () {
...
}
}
Assuming the missing quote after "#toggle is a typo, I'm not sure how you expect your code to work.
Here's how it runs, in prose:
Define a function ArrowDir.
When ready, attach a click handler
When clicked, call ArrowDir
In ArrowDir, define two local variables up and down, each with a function to do something.
There is no return statement, so return nothing
Call the down method of the "nothing" object. ERROR
See?
Try adding return {up:up,down:down}; to the end of your ArrowDir function.
You can create the object this way. In your function you are creating them insdied the scope of itself. SO it is not accessible outside.
function ArrowDir() {
}
ArrowDir.prototype.up = function () {
$("#arrow").attr('src', 'up_arrow.jpg');
};
ArrowDir.prototype.down = function () {
$("#arrow").attr('src', 'down_arrow.jpg');
}
and access it as
$(function () {
if($("#toggle").onclick){
var arrow = new ArrowDir(); // call the constructor to create a new instance
arrow.down(); // invoke the method
};
});
ArrowDir().down() here's your problem. Just because you define a variable in the ArrowDir function doesn't make it a method/property of it. You have to use Prototype Inheritance.
EDIT:
//Something like this:
ArrowDir.prototype.down = function() {
//Do stuff
}
Now you can call ArrowDir.down().
Doing this extends the properties (things it can do) of the object ArrowDir. You're adding a method to it.
The var up and down you have defined inside ArrowDir are not accessible outside the scope of that function.
The simplest way you could fix this, if this is a one-time kind of function, is just to put the up/down behavior in your jQuery function, like this:
$(function () {
if($("#toggle").onclick){
$("#arrow").attr('src','up_arrow.jpg');
} else {
$("#arrow").attr('src','down_arrow.jpg');
}
});
If you just want to namespace these functions for reusability you could make an object literal instead:
ArrowDir = {
up: function(){
$("#arrow").attr('src','up_arrow.jpg');
},
down: function(){
$("#arrow").attr('src','down_arrow.jpg');
}
};
Then you can call: ArrowDir.up() or ArrowDir.down() elsewhere.
For what it's worth, if your goal is just to namespace these functions for reusability, I would say the object literal syntax makes more sense to me.
Or, if you really want to do it as a function call, as Kolink has pointed out, the up/down functions need to be in the return value. You could write that like this...
function ArrowDir() {
var up = function(){
$("#arrow").attr('src','up_arrow.jpg');
}
var down = function(){
$("#arrow").attr('src','down_arrow.jpg');
}
return {up:up,down:down};
}
Or like this...
function ArrowDir() {
return {
up: function(){
$("#arrow").attr('src','up_arrow.jpg');
},
down: function(){
$("#arrow").attr('src','down_arrow.jpg');
}
};
}
Now calling ArrowDir().down() should work.

Scope problem nesting Javascript Objects

I am writing some Javascript code using jQuery to display specially formatted widgets in a browser. I've had success, but now I'm working on refactoring my code for two reasons.
(1) I wish to be able to easily use the widget more than once and have a Javascript object referring to each one.
(2) I wish to do it the right way so that my code is totally reusable and doesn't little the global namespace with all sorts of objects and functions.
I'm having a scoping problem and I wish to fix the problem and improve my understanding of Javascript scope. I've condensed this problem down to a tiny code snippet that illustrates what I'm doing:
function getMyObject() {
var theObject = {
doThis: function () { },
doThat: function () { },
combinations: {
doThisTwice: function () { doThis(); doThis(); },
doThatTwice: function () { doThat(); doThat(); }
}
};
return theObject;
}
var myObject = getMyObject();
myObject.combinations.doThisTwice();
I've declared a function that returns an object.
However, when I try to execute the function combinations.doThisTwice(), the program throws an error saying that doThis() is out of scope. How do I refer to the function doThis in the scope of combinations.doThisTwice?
Update: Thank you kindly for the answer to my question: Replace doThis() with theObject.doThis() inside the function doThisTwice(). This works, but I don't understand why.
I would have thought that the name theObject would not be valid until the end of the object declaration. I think I must misunderstand some fundamental aspect of Javascript... probably because of the C-like syntax.
You need to do:
function getMyObject() {
var theObject = {
doThis: function () { },
doThat: function () { },
combinations: {
doThisTwice: function () { theObject.doThis(); theObject.doThis(); },
doThatTwice: function () { theObject.doThat(); theObject.doThat(); }
}
};
return theObject;
}
var myObject = getMyObject();
myObject.combinations.doThisTwice();
You reference 'theObject' from an outer scope to call the functions in an inner object.
doThis is not defined in the functions scope, so it will traverse up the scope chain, but not find it.
You can reference it by
theObject.doThis();
However, more readable might be if you define your function like this:
function getMyObject() {
function doThis() {};
function doThat() {};
var theObject = {
doThis: doThis,
doThat: doThat,
combinations: {
doThisTwice: function () { doThis(); doThis(); },
doThatTwice: function () { doThat(); doThat(); }
}
};
return theObject;
}
But in this case, whenever you change doThis from the outside, doThisTwice will still reference the original function.
In doThisTwice, use theObject.doThis(); instead of doThis();

How do I access these JavaScript member functions from outside?

I know how to access the below member function when it's written like this:
var blady_blah=
{
some_member_function: function ()
{
}
}
I access it from outside doing blady_blah.some_member_function()
But how do I access the member function when it's written like this:
(function() {
some_member_function: function ()
{
}
})();
Braces, { }, are used to define both object literals and function bodies. The difference is:
var name = {}; // Object literal
Which you may also see written as
var name = {
};
That's just the same but with some space in between so it's still an object literal, and unfortunately it looks very similar to:
var name = function () { // Function body
};
An object can have members:
var name = {
member: "string"
};
Whereas a function cannot; a function has statements:
var name = function () {
do_something();
var result = do_something_else();
};
You can't write
var name = function () {
member: "string"
};
Because you've mixed the two uses of { } together.
A variable can be defined within a function, but it can't be seen outside the function - it's within the function scope:
var name = function () {
var something_useful = string;
};
The second example is a closure (it just happens to have a syntax error inside). Minus the bad syntax, your self-evaluating anonymous function looks like this:
(function() {
})();
If you'd like, you can define functions inside this that will be invisible to the outside world. This is useful if you're interested in maintaining a clean global namespace, for example with library code.
(function() {
function utilityFunctionFoo() {
}
function utilityFunctionBar() {
}
})();
Of course, if you'd like to call any of these functions from the outside world, you're out of luck. Or are you? Actually, there's another way to define a function:
var foo = function() {
}
That's exactly the same as writing:
function foo() {
}
...Except that when written in the second style, you can actually omit the var keyword and create a global variable! Bringing it all together:
(function() {
publicData = "stuff accessible from outside anonymous function";
var privateData = "stuff that stays inside anonymous function";
function utilityFunctionFoo() {
}
function utilityFunctionBar() {
}
usefulFunctionExport = function() {
utilityFunctionFoo();
utilityFunctionBar();
}
})();
usefulFunctionExport();
You can't access it after the function it's in terminates. It's a local variable that goes out of scope when its parent function ends.
You should make the main function be a constructor so that it returns a new instance of a class (you could name it Blahdy_blah) with the member function as one of its properties.
Look up constructors, their return values, and accessing member variables.
If you want to execute the function you need to return an object that exposes the function.
var LIB = (function() {
    var fn = {
member_function : function(){}
};
return fn;
})();
and to call
LIB.member_function();
(function() {
blady_blah.some_member_function();
})();
If you need to add stuff into it you would write it like this.
(function() {
blady_blah.some_member_function(function(){
// Do stuff...
});
})();

Categories

Resources