As below, I create a function displayMsg that displays the content of "object1.msg", which is build after onload event, but it shows undefined.
But if i put
var object1 = new testObject("Hello");
before window.onload, no matter before/after displayMsg() function, it works.
Why is that? and what is the program executing order difference between these two? Thanks...
function testObject(msg) {
this.msg = msg;
}
function displayMsg() {
document.getElementById("msgbox").innerHTML = object1.msg;
}
window.onload = function() {
var object1 = new testObject("Hello");
displayMsg();
}
You're declaring object1 inside a function, therefore it's in that function's scope, and cannot be accessed from another scope.
Try this:
function testObject(msg) {
this.msg = msg;
}
function displayMsg(object) {
document.getElementById("msgbox").innerHTML = object.msg;
}
window.onload = function() {
var object1 = new testObject("Hello");
displayMsg(object);
}
You are creating your object1 object in the scope of the window.onload function.
That means there is no object1 in your display message function.
You can try passing the object as a parameter to your displayMsg() function or just migrate your entire code into the onload function.
EDIT
Just to awnser your question of the load order: Every script that you include gets executed as soon as its loaded by the browser. Using window.onload will delay all code in that function to the point where every single script of the page is loaded. And also note that the order in wich you put scripts in your html file does matter!
The onLoad event is triggered when the page or element (You can use onLoad with DOM elements) is loaded and rendered, so the rest of the javascript code that is located inline is previously read and executed.
What probably happens with you code is that you are defining the object instance variable inside the onLoad callback, hereby the "object1" is out of the scope.
You can try with this:
var object1; // Variable is defined in the global scope
function testObject(msg) {
this.msg = msg;
}
function displayMsg() {
document.getElementById("msgbox").innerHTML = object1.msg;
}
window.onload = function() {
object1 = new testObject("Hello");
displayMsg();
}
<div id="msgbox"></div>
Related
I want to recognize the calling function and one function call it that
The following example illustrates this issue
<script>
var func = (function () {
var check = function (value) {
//detect caller function
var that = arguments.callee.caller;
//I want
//if Buttom One click --> call print in func1
//if Buttom Two click --> call print in func2
};
return {
check:check
}
})();
var func1 = (function () {
var start = function () {
func.check(10);
};
var print = function (value) {
alert(value);
}
return {
start: start,
print: print
}
})();
var func2 ...
</script>
<button id="One" onclick="func1.start()">One</button>
<button id="Two" onclick="func2.start()">Two</button>
Do you have a solution?
Many thanks!
Putting aside the fact that arguments.callee and Function.caller are both non-standard, the reason why it doesn't work is that you are confusing properties with local variables, all that mixed in with closures.
var func1 = (function () {
// ...
})();
This creates a function, runs it and saves the result in func1. Since the return statement of your closure is return { start: start }, at the end of this section of code func1 will contain an object which as a method called start.
When you use var, you're only creating a variable which exists inside that function. Outside of the function, it is no longer accessible. You did store the start function in the returned object, but you never returned print so it doesn't exist anymore.
Instead of going line by line and trying to explain all what is wrong, I'll ask you this: what you were actually trying to do? Don't ask us about your attempted solution which didn't work, but about what the code should do.
I suggest you look at these answers I wrote if you need further explanations on closures and scope.
Understanding public/private instance variables
Do the different methods of creating classes in Javascript have names and what are they?
I've a crazy problem. I'm instantiating an object from a class. Then I want to pass a function from this object to the setInterval function. The whole code block is executed with a keyDown event.
Here's the code:
function doKeyDown(e){
var instance = new Class(e.keyCode);
setInterval(instance.functionToBeExecuded(), 200);
}
The strange thing is that it's getting executed once and then starts to loop an error which states (firebug):
27
SyntaxError: missing ] after element list
[object HTMLAudioElement]
For the sake of completeness:
Class.prototype.functionToBeExecuded = function(){
var node = document.createElement("audio");
//the key is stored in the object (from the Class's constructor)
node.setAttribute("key", this.variable);
}
Does anyone see some fails?
Thanks in advance! =)
P.S.: This is not a duplicate cause I'm not facing the function, function() error. If I'm executing it with (instance.functionToBeExecuded, 200) it happens just nothing.
What I've found out so far is that the problem must be in the scope somehow. If I do it like this:
function doKeyDown(e){
var instance = new Class(e.keyCode);
setInterval(instance.functionToBeExecuded, 200);
}
Class.prototype.functionToBeExecuded = function(){
console.log(this);
var node = document.createElement("audio");
//the key is stored in the object (from the Class's constructor)
node.setAttribute("key", this.variable);
}
I'm getting a looping console output with "window". So the function is executed in the window's scope. But why? And how to work around?
Console output:
Window index.html
The workaround would be: wrap it using another function instead of calling method directly
function doKeyDown(e){
var instance = new Class(e.keyCode);
setInterval(function(){
instance.functionToBeExecuded()
}, 200);
}
This would give output many of these:
Class {functionToBeExecuded: function}
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 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.
At the very beginning of the javascript file, I have:
var lbp = {};
lbp.defaults = {
minLength: 40
};
I can successfully alert it afterwards, with:
alert(lbp.defaults.minLength);
But as soon as I put it inside a function, when I alert, I get "Undefined". What gives, and how do I avoid this? Is it absolutely necessary to pass this variable into each function, for example, by doing:
function(lbp) { alert(lbp.defaults.minLength); }
I would have thought that defining it first, it would attain global scope and not be required to be passed in?
Thanks in advance for enlightening me :)
====================================
EDIT:
The problem seems like it might be my initialize function is itself defined within lbp. Is there any way to use this function var, and still use lbp vars inside it?
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
The full bit of code looks like this:
<script type="text/javascript">
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
window.onload = lbp.initialize;
</script>
Are you actually passing lbp as the argument? Otherwise the parameter with the same name will hide the global variable.
Use this.
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(this.defaults.minLength);
};
window.onload = function() { lbp.initialize(); };
If you call initialize as a method of lbp, this will point to lbp. When you assign a function to an event handler, such as window.onload, you are essentially copying the body of that function to the object on which the event handler is defined. So,
window.onload = lbp.initialize
is the same as
window.onload = function() {
alert(this.defaults.minLength);
};
Now, this is pointing to window, which is obviously not what we want. By wrapping the call to lbp.initialize() in a function, we preserve the context of this within that function and we can make sure that it always points to lbp. Check out this for a more complete explanation.
This works for me from javascript console in Firefox:
javascript:var lbp={}; lbp.defaults={minLength: 40};function xx() { alert(lbp);alert(lbp.defaults);alert(lbp.defaults.minLength); }; xx();
Gives output [object Object], [object Object], 40.
So, it seems there might be some problem with some associated code, which is not shown?
In the original code where you are trying to use lbp in a function. You are passing lbp in as an argument. This would hide the lbp from the global scope with a local (to the function) variable of the same name (unless when calling the function you passed lbp in again).
//this is what you have and will not alert a thing other
//and will probably throw an error
function(lbp) { alert(lbp.defaults.minLength; }
//should just be this with no argument. this will allow
//the function to see lbp in the global scope.
function() { alert(lbp.defaults.minLength; }
by passing lbp as a parameter in the first function it is not seen inside the function as the global object, but the local argument.