Hey I have this code right here:
http://pastie.org/534470
And on line 109 I get an error saying "TypeError: Result of expression 'this.allVarsDefined' [undefined] is not a function."
Scope in javascript is confusing to me. Can anybody see what my problem is? Also do you guys know of any articles that would help me learn about scope in javascript. This is my first time really using JS :)
This looks prototype-based. You probably need to set up your notification callback like this:
setTimeout(this.notify.bind(this), 5000, track);
so that the notify function is bound to the Scrobbler object and gets this set to the Scrobbler object instead of the event triggering the function when the timeout occurs.
If I'm wrong on you using prototype, you can probably achieve the same effect using
var that = this;
setTimeout( function() { that.notify(); }, 5000, track );
Try changing line 109 from
setTimeout(this.notify, 5000, track);
to
setTimeout(function(){this.notify()}, 5000, track);
What this will do is create "closure" (function(){this.notify()}) that includes the "this" variable in it, and "this" includes this.allVarsDefined, so you should stop getting that error.
I think the problem with your old code is that when you write "this.notify" you were just yanking the function out of the instance of the object and passing it to setTimeout, but you were not passing any information about the object itself. That would be okay if the notify function did not refer to "this", but since it does refer to "this", you need to use a closure.
You would benefit from reading more about Javascript closures. Here is a decent article. I also recommend the great book Java Script: The Definitive Guide 5th Edition by O'Reilly. It only costs like $50 but it is well-written and will help you immensely if you are trying to write a web-app in javascript.
If my solution does not work, then simplify your code down to the most basic thing that you think should work and does not work, and then post it here.
Related
Dear Javascript programmers,
Google's Closure Library is always good for driving people crazy. I hope you can help me on this issue:
I want to catch the ondevicemotion-Event by javascript within a function within the Closure lib.
Without Closure everything works fine with the following code which I grabbed from this page (thanks to the author): http://www.peterfriese.de/how-to-use-the-gyroscope-of-your-iphone-in-a-mobile-web-app/
The following snippet shows "my" code:
if (window.DeviceMotionEvent != undefined) {
console.log("DME");
window.ondevicemotion = function(e) {
console.log("ODM");
// handle events like e.rotationRate
...
}
}
This works perfectly in a standalone html page. Both console.logs are triggered.
In contrast, Closure seems to have a problem with window.ondevicemotion = function(e) { because the console logs "DME" but not "ODM".
There are no compiler warnings or errors.
Has anybody recognized such a problem, too? I sadly have no idea why Closure acts so stupid (more probably I am so stupid). ;-)
Thanks for reading! Any help appreciated!
Running in ADVANCED_COMPILATION, the Closure Compiler minimized and obfuscated window.ondevicemotion for me, so I'll assume that is your problem as well. There are two ways to step around this:
1. Use bracket notation to set / access the property.
The Closure Computer will not rename any properties that are referenced via the bracket notation. The following should not get obfuscated (though, potentially, it could get rewritten as window.ondevicemotion):
window['ondevicemotion'] = function(event) { ... }
2. Use an extern to let the compiler know not to rename this property.
Similar to the situation above, the Closure Compiler takes a hint and doesn't rewrite the property, leaving it as is. This, however, has a nice benefit of giving you some type checking, since you're defining what the signature of the extern is to the Closure Compiler:
/**
* #param {goog.events.Event} event
*/
window.ondevicemotion = function(event) {};
The decision of which one to use is ultimately yours. In this scenario I would most likely go for the second option and only go back to the first if there was some reason you could not use externs.
I've got a piece of code I'm working with that was handed down to me by a previous developer. I am just trying to understand it better and not just use it naively. Here's the code:
slides.paginator.click(function (e) {
e.preventDefault();
interval.stop();
switchSlide($(this).index());
interval.start();
});
The part that I do not understand is the argument e that is being passed through this anonymous function. I have seen this before and I thought it had something to do with closures, but again, I am not sure. Can anyone give me a little insight into exactly how this parameter e works? I have seen it in other cases as well, such as with jQuery's AJAX methods.
Even pointing me in the right direction towards an article would be a great help. Thanks!
"e" comes from "event", check the jquery .click() docs http://api.jquery.com/click/
function(e){} replaces "handler(eventObject)"
I am trying on some code here,
var cat={
col:"Red",
getCol:function(){
document.writeln(this.col);
}
}
function getCol(){
document.writeln(cat.col);
}
$(function(){
$("#button1").click(cat.getCol);
$("#button2").click(getCol);
})
But I got undefined for button1, "Red" for button2. Can someone tell me why?
And if I change it into $("#button1").click(cat.getCol());, I got the "Red" I need...
First of all
$("#button1").click(cat.getCol);
gives you undefined because the body of cat.getCol uses this which ain't cat when this thing runs. I would suggest using Function.prototype.bind here, or several of the other variants if you are worried about cross-browser compatibility. There are many published solutions to the problems of setting "methods" as event handlers and ensuring that this stays bound to the enclosing object.
Next
$("#button2").click(getCol);
works fine because getCol uses cat directly.
Finally
$("#button1").click(cat.getCol());
is terribly wrong. The expression cat.getCol() is a call which returns undefined. This is not a good value to set for a click handler. You just saw the document.write taking place, but not in response to a click.
ADDENDUM
Live demo using bind
Generally in JS, this refers to the owner of the function .. So, in both cases when that function is called, this would resolve to the (jQuery object of the)element that has been clicked.
In the first case, this is not 'cat', so col is not defined. Thus, it gives undefined.
In the second case, no this, so cat.col resolves to Red.
I think you need to do some reading about JS functions, this, anonymous functions .. http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/ is a good place to start.
This on MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this
Excuse me first. because i don't know this is question is valid or not. i if any one clear my doubt then i am happy.
Basically : what is the different between calling a method like:
object.methodname();
$('#element').methodname();
calling both way is working, but what is the different between, in which criteria make first and second type of methods. is it available in the core javascript as well?
In case if i have a function is it possible to make 2 type of method call always?
Can any one give some good reference to understand correctly?
Thanks in advance.
The first syntax:
object.methodName();
Says to call a function, methodName(), that is defined as a property of object.
The second syntax:
$('#element').methodname();
Says to call a function called $() which (in order for this to work) must return an object and then call methodname() on that returned object.
You said that "calling both way is working," - so presumably you've got some code something like this:
var myObject = $('#element');
myObject.methodname();
This concept of storing the result of the $() function in a variable is commonly called "caching" the jQuery object, and is more efficient if you plan to call a lot of methods on that object because every time you call the jQuery $() function it creates another jQuery object.
"Is it available in the core javascript as well?" Yes, if you implement functions that return objects. That is, JS supports this (it would have to, since jQuery is just a JS library) but it doesn't happen automatically, you have to write appropriate function code. For example:
function getObject() {
return {
myMethod1 : function() { alert("myMethod1"); return this; },
myMethod2 : function() { alert("myMethod2"); return this; }
};
}
getObject().myMethod1().myMethod2();
In my opinion explaining this concept in more depth is beyond the scope of a Stack Overflow answer - you need to read some JavaScript tutorials. MDN's Working With Objects article is a good place to start once you have learned the JS fundamentals (it could be argued that working with objects is a JS fundamental, but obviously I mean even more fundamental stuff than that).
The difference is very subtle.
object.methodname();
This is when JavaScript has the object at hand.
$('#element').methodname();
If you are using jQuery, you are asking jQuery to select the object that has the id of #element. After that you invoke the method on the selected object.
I'm trying to tidy up some javascript code and one of the steps is removing all useless (or plain wrong) global variables that have slipped in from errors like:
for (prop in obj) { ...
instead of
for (var prop in obj) { ...
JSLint helps a bit in finding out this nastiness, but it is not 100% foolproof when the nastiness happens at runtime.
I already tried to add some monitoring code that routinely checks the global scope logging to the console if some new variable is detected, and that helped some more, but when it tells me that a new global variable named "i" has been detected ... well, it's a mess finding out where that happened in thousands of lines of code.
So here we come: is there a better way/tool/script/whatever to find the little pests?
My dream is something like a Firebug plugin that stops the execution whenever a new global variable is created...
Thanks!
You may find this bookmarklet useful.
Also, checkout this answer: How to detect creation of new global variables?
You can now intercept variable definition as explained on this similar question
window.__defineSetter__('sneakyVariable', function() {
debugger
})
and you'll be able to find where it was defined
I wonder if you could set a timeout to create a list of all global variables and then compare that against the last time the timeout fired. I found this on Stack Overflow, and maybe you could use this code in conjunction with a setTimeout() to get what you want.
Blockquote
Yes and no. "No" in almost every situation. "Yes," but only in a limited manner, if you want to check the global scope. Take the following example:
var a = 1, b = 2, c = 3;
for ( var i in window ) {
console.log(i, typeof window[i], window[i]);
}
Stack Overflow link: Getting All Variables In Scope
well, I wrote this long time ago, so code sucks, but it does the job: https://gist.github.com/1132193
paste in the firebug console or include as a script.
You say, you are trying to tidy up some code.
In that case - use IDE, like NetBeans PHP (free) or JetBrains WebStorm (30$). They both color global variables, and do lots of other useful stuff ;)
If your polling script will still detect creation of global variables - trace down offending functions, and make them suffer ;) Eventually, the code will become clean.