I have a really simple function:
function loading (text, id) {
console.log("test");
$('#loadingsts').append('<div id="loader"></div>');
}
that is defined in a javascript file which is loaded with the html via:
<script src="js/loader.js"></script>.
I want to execute that function in another js file so I need to have the function be global, right?
If I execute is like this, the console.log() works but the but the append doesn't. If I put the function into a $(function() {}); it says loading() not defined.
I also don't want the function to be executed on loading but only when called.
How can i make it work.
I looked at these questions already but they didn't help
Question1
Question2
Question3
A method created outside any other method is global by nature. If you are creating a method inside another method, you can make it global by attaching it to the window object if you like, or another object that is global itself, in which case you'd have to access it by thatObject.yourMethod()
var objectOutsideAnyMethod = {};
(function(){
function ImNotGlobal(){}
window.IAmGlobal = function() {};
objectOutsideAnyMethod.meToo = function(){};
})();
IAmGlobal(); //valid
objectOutsideAnyMethod.meToo(); //valid
ImNotGlobal(); //error
There's a little something about scope I just keep getting confused about:
this.init = function(){
var t = this;
setTimeout(function(){
// why is t still available here?
t.initgame();
// but not this?
this.initgame();
}, 500);
}
this.initgame = function() {
// yada yada
}
I get that inside an anonymous function, scope is different that outside of it.
But why, in the above example, is the variable "t" available inside the timeout function, while "this" is not working?
The problem is that setTimeout is called with window as scope.
Using a dedicated variable to store this (t) is a perfectly valid and usual solution.
On modern browsers, bind is sometimes convenient :
setTimeout((function(){
// use this
}).bind(this), 500);
When the anonymous function runs, it is no longer running as a member function of init, but rather a top-level function of window. As a result, this.initgame() has no meaning.
For example, running console.log(this) inside the timeout function returns as follows:
Window {top: Window, window: Window, location: Location, external:...
When you use var t = this, you assign reference to the current object, which works.
I have a function localised to the main function and i want to use this to call it but it doesn't seem to work.
My code has:
function option(room,slot){
var div_id = document.getElementById(room);
var opacity = window.getComputedStyle(div_id).opacity
transition_opacity(div_id,opacity,0,function(){this.load});
function load(){
console.log('test'); //does not happen
}
}
Have i misunderstood the use of this or is the scope lost when i use function(){} to call load?
From your code it is not obvious, what object this could refer to. It depends on how option is called. However, if you define the load function inside of the option function anyway, it is best to just reference it directly. You will have to move the declaration of test above the transition_opacity call though:
function option(room,slot){
var div_id = document.getElementById(room);
var opacity = window.getComputedStyle(div_id).opacity;
function load() {
console.log('test');
}
transition_opacity(div_id,opacity,0,load);
}
As you can see, I just reference load directly. You could make another function which calls the load function inside (i.e. function() { load(); } – note the parentheses which calls the function) but that would give you no benefit but would just add another unneeded function to the stack. So just refer to the actual function itself.
For more information on the this keyword, check out this question. Spoiler: It’s more complicated than you would expect.
The scope of this is lost in this instance, probably pointing to the document. You can capture this to a variable in the outer scope to make this work as intended.
var context = this;
transition_opacity(div_id,opacity,0,function(){context.load();})
The above will not work however. This is because load does not exist on the context of this. You would need to define the load function as such:
context.load = function(){
console.log('test');
}
Both.
First, your load function is not a member/property of any this, the way you have it coded. Your load function is simply a nested function that exists within your option function, as has been sort of implicitly noted in other responses.
In your option function, if you want 'load' to become a member of 'this', you'd need to say so, like this:
function option(){
this.load = function(){}; // now load is actually a property of whatever this is
}
Second, you and the other poster are correct that 'this' is no longer the same 'this' by the time your anonymous function is called.
Whenever you call a function, a brand new 'this' is created and exists within the scope of that function. If you just call a function like this:
transition_opacity(args);
.. then within transition_opacity, 'this' just refers to the window object, or maybe window.document. For 'this' to refer to anything other than window or window.document, you need to (in effect) do one of the following:
myObject.transition_opacity(args);
transition_opacity.call(myObject, arg1, arg2, ..);
transition_opacity.apply(myObject, argArray);
or
var myObject = new transition_opacity(args);
In each of those cases, within transition_opacity, 'this' refers to myObject (or, well, in the last case, it refers to a new object that is being created and assigned to myObject).
Here is a way to do what it looks like you're trying to do:
var MyNamespace = {
option: function(room,slot){
var div_id = document.getElementById(room);
var opacity = window.getComputedStyle(div_id).opacity;
var _this = this;
transition_opacity(div_id,opacity,0,function(){
// Careful! Inside here, 'this' is just window or window.document,
// unless transition_opacity sets it to something using call or apply,
// in which case that 'this' is probably not the 'this' you want.
// So carefully refer to the saved instance of 'this':
_this.load();
});
},
load: function(){
console.log('test'); // now it should happen
}
}
.
.
MyNamespace.option(room, slot); // inside option, 'this' is MyNamespace.
Here's another way to do it:
function MyClass(){};
MyClass.prototype = {
// all the same stuff that is in MyNamespace above..
};
.
.
var myObject = new MyClass();
myObject.option(room, slot);
Clear as mud?
Just use
transition_opacity(div_id,opacity,0,load);
You have defined a 'load' within another function as an 'Function Declaration', so now it is only accessible within 'option' function and in other functions defined in this one by name 'load'. You can't access it by using 'this.load' no matter what 'this' is. If you want to access 'load' function as 'this.load' you can try this example to understand how 'this' keywoard works
// Function Declaration
function f1(callback){
callback();
};
// Function Declaration
function f2(){
// Function Expression
this.load = function(){
console.log("test");
};
f1(this.load);
};
var obj = new f2(); // test, this == obj, so obj.load() now exists
obj.load(); //test, this == obj
f2(); //test, this == window, so window.load() now exists
load(); //test, window is the global scope
I am in a position where I need to "update" a function that exists in another javascript file. The file looks like this:
function jf(){
alert('1');
}
//call jf periodically
jf();
The second js file, which is loaded after looks like this:
console.log(jf);
console.log(window.jf);
var func=function(){
alert('2');
};
jf=func;
window.jf=func;
The first log successfully returns the original jf method, the second doesnt. The first set seems to set the local variable jf, and the second does basically nothing. Is there a way to achieve this functionality?
According to Javascript closures - behavior of overridden functions from the global scope
var done = and function done do basicaly the same thing. They will shadow the outer definition in the inner scope but they will not replace it on the outer scope.
This means you can only override your initial definition of function jf() if you are in the same execution context. Otherwise, replace function jf(){ ... with window.jf = function(){...
Also, running your tests in an inspector console might help.
First, use variables:
var jf = function () {
alert('1');
};
jf();
Then the second bit should work fine:
var func = function () {
alert('2');
};
jf = func;
jf();
I am using a plugin JS and need to call a function in it.
It is having functions inside a variable like,
var win = window;
var Page = function(pageOptions, callback) {
function abc(){
--------
}
function xyz(){
------
}
};
win.Sales = {
Page: Page
};
Now, I need to call a function abc(). How can I call it.
Already tried with win.Sales.page.abc();.
Please help me out on this. Thanks in advance.
You cannot do that with your configuration because the functions are local or private.
You should make them accessible globally like:
var Page = function(...) {
...
};
Page.abc = function() {
...
};
That way, abc is a property of Page, and you can then access it like Page.abc and execute it like Page.abc(). Functions are basically also objects so they can have properties too.
You cant call function abc since it is declared as a private member of the function referenced by variable Page.
If you want to call the function You have to make it as a property of the variable Page.
var Page = function(){
.........
.........
.........
}
Page.abc = function(){
}
But there is another problem of variable scoping like if there is another variable x defined in function Page and used inside function abc, it will not work.
Anyway since you've said it is a js plugin I do not think it will be possible for you to change the function Page. So the answer will be No you cannot do that.