Ok, I have being trying to find a solution for this for the past 3 hours...
I want to be able to create my own library, accessible function within function with function etc.
Here's what I want to do...
var outer=function()
{
this.inner=function()
{
this.innermost=function()
{
alert("innermost");
}
}
}
var outer=new outer;
function start()
{
//I want to call it like this but fails!
outer.inner.innermost();
}
Now this fails when I try to call the innermost. But if I just have a a function within a function, it works. For example:
var outer=function()
{
this.inner=function()
{
alert("inner");
}
}
var outer=new outer;
function start()
{
// this works
outer.inner();
}
All the examples I've found only show a function within a function.
I want to be able to create my own library of functions. With an easy way to access them, e.g.:
MyLib.SubLib.SubLib2.function
MyLib.SubLib.SubLib2.property
Any help on the matter would be greatly appreciated. Would I have to learn and use prototypes?
First of all, this is how you do it:
var outer = function() {
this.inner = {
innermost: function() {
alert("innermost");
}
}
}
var outer = new outer;
outer.inner.innermost();
The reason why it didn't work the way you did it is because you define a function inner - so outer.inner is a function. You could do var inner = new (outer.inner)(); and then call inner.innermost(); but that's obviously ugly and not what you want.
Related
I am currently trying to learn javascript and what I want to achieve is to call a function, from outside the main function. For a better idea, I left the code which I am currently exercising on. I will be extremely grateful If someone can explain to me why exactly this function is not working. Thank you in advance.
function One_Main(){
function Alpha(){
console.log("Alpha");
}
}
One_Main();
function Two_Main(){
Alpha();
}
Two_Main();
Alpha() is in the scope of One_Main, you can't see it from the global scope. To call Alpha() from outside of One_Main you need to declare it outside of that function.
function Alpha(){
console.log("Alpha");
}
function One_Main(){
Alpha();
}
One_Main();
function Two_Main(){
Alpha();
}
Two_Main();
It's not working because Alpha is not visible outside of One_Main.
To make it visible, you can define One_Main as an object, then make Alpha a property of One_Main.
To fix your code, do this:
function One_Main() {
this.Alpha = function() {
console.log("Alpha");
}
}
// Make it visible
Alpha = new One_Main().Alpha;
function Two_Main() {
Alpha();
}
Two_Main();
ES2015 Style
class One_Main {
constructor() {}
static Alpha() {
console.log("Alpha");
}
}
// Make it visible
Alpha = One_Main.Alpha;
function Two_Main() {
Alpha();
}
Two_Main();
As a simple property in pure JS
function One_Main() {}
One_Main.Alpha = function() {
console.log("Alpha");
}
// Make it visible
Alpha = One_Main.Alpha;
function Two_Main() {
Alpha();
}
Two_Main();
You might want to read about scoping in javascript to understand the problem.
https://scotch.io/tutorials/understanding-scope-in-javascript
The function Alpha is not visible inside the Two_Main function
PS: Debugging is useful to learn more about the error. In Chrome you can right click and select Inspect element and look at the console to debug javascript.
Checkout https://raygun.com/blog/debug-javascript/ for more information
I dont know what tutorial are you studying, maybe you are reading about currying method, if that is the case, you can make:
function One_Main(){
function Alpha(){
console.log("Alpha");
}
return Alpha;
}
One_Main();
function Two_Main(){
One_Main()();
}
Two_Main();
I have this weird problem. I am trying to initialize a datepicker inside a document ready function:
$(document).ready(fncInitialize);
function fncInitialize() {
fncBindControls();
}
function fncBindControls() {
var objDate = $(this).find("input[data-datepicker='True']");
objDate.datepicker();
}
The problem is this doesn't work. The datepicker is not working. Fortunately when I reposition the element:
function fncInitialize() {
var objDate = $(this).find("input[data-datepicker='True']");
objDate.datepicker();
fncBindControls();
}
function fncBindControls() {
}
This code works. But why? I just put the datepicker on another function for maintainability but it doesn't work. Do I really need to put it inside the first function of document ready?
The issue is because in the second function you've lost the scope of this. You need to either pass it as a parameter:
$(document).ready(fncInitialize);
function fncInitialize() {
fncBindControls(this);
}
function fncBindControls(el) {
var objDate = $(el).find("input[data-datepicker='True']");
objDate.datepicker();
}
Or provide a scope when you call the function:
function fncInitialize() {
fncBindControls.call(this);
}
I just can't reach the function inside function using only HTML.
How to call setLayout() using only HTML or is it able to call only in Javascript?
<button onclick="customize.setLayout('b.html');">Click Please</button>
Javascript:
function customize() {
function setLayout(text) {
var selectedLayout = text;
layout += selectedLayout;
$.get(layout, function (data) {
$("#layout-grid").html(data);
});
}
}
It isn't possible to call setLayout at all.
Functions defined in other functions are scoped to that function. They can only be called by other code from within that scope.
If you want to to be able to call customize.setLayout then you must first create customize (which can be a function, but doesn't need to be) then you need to make setLayout a property of that object.
customize.setLayout = function setLayout(text) { /* yada yada */ };
Multiple ways to call a function within a function. First of all, the inner function isn't visible to the outside until you explicitly expose it Just one way would be:
function outerobj() {
this.innerfunc = function () { alert("hello world"); }
}
This defines an object but currently has no instance. You need to create one first:
var o = new outerobj();
o.innerfunc();
Another approach:
var outerobj = {
innerfunc : function () { alert("hello world"); }
};
This would define an object outerobj which can be used immediately:
outerobj.innerfunc();
if you insist to do it this way, maybe define setLayout and then call it,
something like this:
<script>
function customize(text, CallSetLayout) {
if (CallSetLayout) {
(function setLayout(text) {
//do something
alert(text);
})(text);
}
}
</script>
<button onclick="customize('sometext',true);">Click Please</button>
then you can decide if you even want to define and call setLayout from outside
Simple answer: You can't call setLayout() with this setup anywhere!
The reason being, setLayout() will not be visible outside of customize() not even from other JavaScript code because it is defined locally inside customize() so it has local scope which is only available inside customize(). Like others have mentioned there are other ways possible... (^__^)
You can return the response of setLayout() by returning it as a method of customize() and use it in your HTML like customize().setLayout('b.html'); e.g.
<button onclick="customize().setLayout('b.html');">Click Please</button>
JavaScript:
function customize() {
var setLayout = function (text) {
var selectedLayout = text;
layout += selectedLayout;
$.get(layout, function (data) {
$("#layout-grid").html(data);
});
};
return {
setLayout: setLayout
};
}
Another Approach
You can also define your main function i.e. customize as Immediately-Invoked Function Expression (IIFE). This way you can omit the parenthesis while calling its method in HTML section.
<button onclick="customize.setLayout('b.html');">Click Please</button>
JavaScript
var customize = (function () {
var setLayout = function (text) {
var selectedLayout = text;
layout += selectedLayout;
$.get(layout, function (data) {
$("#layout-grid").html(data);
});
};
return {
setLayout: setLayout
};
})();
You need to treat it as object and method
<button onclick="customize().setLayout('b.html');">Click Please</button>
Sorry I had to edit this code for more clarification
function customize() {
this.setLayout = function setLayout(text) {
var selectedLayout = text;
layout += selectedLayout;
$.get(layout, function (data) {
$("#layout-grid").html(data);
});
}
return this;
}
function layoutMod() {
standardId = document.getElementById("standard");
fancyId = document.getElementById("fancy");
standardId.onclick = function() {
standard();
};
fancyId.onclick = function() {
fancy();
};
};
How can I use the onclick events defined above in a function??? Is it a good practice to load the function at page load?? I need to define in a function the onclick event beacuse I don't want to use global variables.
What you've written should work. However, you should note that by not using the var keyword, you're still creating global variables inside of your function. I would suggest...
function onloadHandler() {
document.getElementById("standard").onclick = function() {
// Do something
};
document.getElementById("fancy").onclick = function() {
// Do something else
};
};
It can get messing when you nest functions inside of each other. In this case, I would suggest removing the outer function so that your code looks like this:
document.getElementById("standard").onclick = function() {
standard();
};
document.getElementById("fancy").onclick = function() {
fancy();
};
The code does not need to be in a function, it will automatically be run on page load. Since you don't want global variables, just don't use variables at all.
I'm really sorry, but i can't figure out why it doesn't work. printStr() can access variable only defined in Foo constructor, but not in private function, that got triggered on mousedown event. Is there any way to access string without declaring printStr inside getBotheredByBrendanEich func?
function Foo(elem) {
elem.on('mousedown', getBotheredByBrendanEich);
function getBotheredByBrendanEich() {
var string = 'its just werks!';
elem.on('mouseup', printStr);
}
function printStr() {
console.log(string);
}
}
var test = new Foo($('#test'));
Your variable string is a local variable inside of the function get...() and is ONLY available inside of that scope. Local variables are only available within the function they are declared in, which in this case is your get...() function
If you want it available in a broader scope so that printStr() can use it, then you have to declare it at a higher scope.
You could solve this by using an anonymous function declared in the same scope:
function Foo(elem) {
elem.on('mousedown', getBotheredByBrendanEich);
function getBotheredByBrendanEich() {
var str = 'its just werks!';
elem.on('mouseup', function() {
console.log(str);
});
}
}
var test = new Foo($('#test'));
Or, you could pass the argument to the event handler with .bind():
function Foo(elem) {
elem.on('mousedown', getBotheredByBrendanEich);
function getBotheredByBrendanEich() {
var string = 'its just werks!';
elem.on('mouseup', printStr.bind(this, string));
}
function printStr(arg) {
console.log(arg);
}
}
var test = new Foo($('#test'));
Or, you could move the variable to a higher scope so it can be shared:
function Foo(elem) {
elem.on('mousedown', getBotheredByBrendanEich);
var str = 'its just werks!';
function getBotheredByBrendanEich() {
elem.on('mouseup', printStr);
}
function printStr() {
console.log(str);
}
}
var test = new Foo($('#test'));
In all cases though, this structure is troublesome because you've adding a new mouseup event handler everytime the mousedown event occurs. This means you will get multiple mouseup handlers after only a couple clicks. This is rarely ever what you really want to do.
I would suggest this which will not suffer from that problem:
function Foo(elem) {
var str = 'its just werks!';
elem.on('mousedown', function() {
// whatever code you want here
});
elem.on('mouseup', function() {
console.log(str);
});
}
var test = new Foo($('#test'));
One more comment. Your code doesn't show any reason to actually use a constructor here. It appears like you could just implement a normal function call since there is no object instance data.