Contending with JS "used before defined" and Titanium Developer - javascript

I have a lengthy JavaScript file that passes JSLint except for "used before it was defined" errors.
I used normal function declarations, as in...
function whatever() {do something;}
as opposed to...
var whatever = function(){do something;};
and consistent with Steve Harrison's reply to an earlier post...
Assuming you declare all your
functions with the function keyword, I
think it becomes a programming-style
question. Personally, I prefer to
structure my functions in a way that
seems logical and makes the code as
readable as possible. For example,
like you, I'd put an init function at
the top, because it's where everything
starts from.
... I like seeing the functions in an order that makes sense to me.
The script functions perfectly in the several browsers tested (e.g., FireFox, Safari, Mobile Safari, Fennec, IE, Chrome, Midori, etc.).
Here's the problem: I want to use the script inside of an iPhone app being built with Titanium but its compiler stops with "used before defined" errors.
How can I get around this?
This might be a stupid question but also... If functions need to be called in a particular order, how does one resolve the matter of a called function needing to call back to the function that originally called it? For instance...
function buildMenu(){
Display a list of five menu items, each of which calls a function to build the associated screen.
}
function screen1() {
Display the screen associated with menu item #1.
}
If the functions need to be declared in order, function screen1 would need to precede function buildMenu. But what if, under certain conditions, screen1 cannot be built and hence wants to redisplay the menu (i.e., calling a function that is technically not yet declared)?
Oh yeah... one more question: Are there websites or programs that automatically re-sequence the functions rather than requiring the programmer to do it manually?

No, EM's answer is NOT the right solution. Try running this JavaScript:
(function () {
foo(); // right
var foo = function () {
console.log("wrong");
};
foo(); // wrong
function foo() {
console.log("right");
}
foo(); // wrong
}());
This is because the interpreter will first read the function declaration, create the name foo as a function that prints "right", then reads the var statement, and find that there is already a name foo so it will skip creating a new variable with the value undefined, as normally happens. Then it processes the code, line-by-line, which includes an assignment to foo. The function declaration does not get reprocessed. Maybe this will behave differently in Titanium, but try this in Firebug and you'll get what I got.
A better solution is:
var screen1, buildMenu;
screen1 = function () { buildMenu(); };
buildMenu = function () { screen1(); };
This will also pass JSLint, and produce the correct behavior.

Related

Javascript * is not a function (prototype function)

Coming from a C++ background, trying to work with an OO language that doesn't have explicit typing is a little more than a headache.
So I have dynamic elements for a webpage that are "controlled" by objects since there are tons of stuff I need to manage on each for it to work. The element is just the visual output of the data inside of the object itself, that's all I really need it for.
Except that I need the object to perform an internal function when it's clicked. That seems to be the biggest source of my headache thus far.
Javascript:
function onClick(file) //The external onClick function I use to try to get it to call from.
{
file.state = INUSE;
file.checkState();
}
function fileObject () { //The file object itself
this.element;
this.newElement();
//initialize stuff for the object
}
fileObject.prototype.newElement = function() { //creates a new element and sets its event listener
this.element.click(function() {onClick(this)});
}
fileObject.prototype.checkState = function() {/*does stuff*/} //apparently this is "not a function"
The error I get exactly is "file.checkState is not a function" from Firefox's console panel.
I'm still new to javascript, but after doing some debugging, I've come to find out that it's explicitly the onClick(this) function that is causing all of the errors. When used with something else, the onClick function works perfectly, but for some reason, the this keyword doesn't appear to actually be sending the reference to the fileObject since all checks show file being undefined when inside of the onClick scope.
Is there something fundamentally wrong about the way I'm trying to do this or am I just missing a step (or adding something that I don't need) that will help get this snippet working.
So you know, your initial problem isn't actually handling the action, but listening to it. click will trigger a synthetic click event, rather than liste for one.
You want ... .element.addEventListener("click", callback); that said, you face a second problem, immediately thereafter.
I will leave my example code as you've written it to not confuse the matter...
But when you see click( ) know that I mean subscribing with addEventListener, if element really does mean a browser DOM element. If it's not a standard browser element, and your own API, then ignore the previous portion, and carry on.
this is dynamically bound at the invocation time of the function (not at definition time).
The nearest function, scoped above, is your callback function that you are passing into .click( ... ).
Which is entirely different than the this which you mean outside of the callback.
Whatever is on the left-hand side of the dot is the this context for the duration of that particular invocation.
Needless to say, click() doesn't know enough to bind the this you mean, to the left-hand side of your callback.
The solution (or one of many) is to use lexical scoping and/or closure to retain the value of the object you mean.
// easy but messier
var fileObject = this;
... .click(function () { onClick(fileObject); });
// Cleaner with thunks:
function clickHandler (onClick, obj) {
return function () { onClick(obj); };
}
... .click(clickHandler(this));
Coming from c++ the way Javascript handles this will seem a little crazy, it looks like here you need to tell the function you've defined what this is - like so:
this.element.click(function() {onClick(this)}.bind(this));

How to know if a function is called from the javascript console?

I want to know how can we hide a function from the javascript console so that it can't be called from it.
To let you better understand the problem , suppose that I have a javascript function that adds some records on the database using Ajax, and anyone else can use this function from the console to add as many records as he wants on the database. I want the function to be called from the web application and not from the console... I tried to obfuscate the code to hide it but we can still find the function from Google Chrome javascript console.
No matter how much you obfuscate and hide your code, any javascript that can be executed on the client side can be executed in the console and you should always be running permissions/security checks on the server side if you wish to have any real control over the security of such functions.
That being said, you can restructure your code inside an immediately invoked function expression which will not be callable as easily from the console as usual like so:
(function() {
var myUncallableFunction = function() { alert('meow'); }
})();
the function myUncallableFunction will only be able to be called from within the parent function as it is a local variable to that parent function and is therefore inaccessible outside of it.
You will still be able to call this function inside of that parent however like so:
(function() {
var myUncallableFunction = function() { alert('meow'); }
myUncallableFunction();
})();

anonymous functions javascript, how to access source code?

I got some JS Code that gets inside a random Anonymous js function.
I want that code (for example alert('hello') ) to dump/alert
the entire script block/object which it was injected into.
kinda like document.body.innerHTML but for the anonymous function block
result should be like :
Function()({ somecode; MyAlert(...) } )()
or
Try { some code; mycode; } catch(e) { }
Mind your terms. "(browser) script block" literally means script element's code by the spec.
Use "javascript block" or "javascript object" to mean a block or an object.
Do not create confusing new terms; do read and research.
Blocks are not objects; they are language statements.
Just like you cannot "get the code/variables of current line", you cannot "get the code/variables of current block", try block or not.
Stepping back, for now you can use Function.caller to get the function calling your code:
var mycode = function me(){ if ( me.caller ) alert( me.caller.toString() ); };
(function(){ var some = 'code'; mycode(); })();
// Alert "function(){ var some = 'code'; mycode(); }", even when it is anonymous
Note that you get the whole function's code, not the function block's code which excludes parameters and function name.
Function.caller may be removed in future, like arguments.caller. (Both are troubles. What if a cross origin function on the call stack contains private api key code? How should js engines inline your code?)
When the time comes, or when caller is null (when it is global code), you may still be able to get textual stacktrace (new Error().stack) and current script element (document.currentScript), but their capabilities are pretty limited.
You can get a script element's code - if any - with its textContent or innerHTML property.
Your question sounds like an XY Problem. You want to do something that no modern language is meant to do, but never say for what purpose.
Try to describe your real problem.
Functions have a toString() method. (Yes functions have methods!)
var fn = function() { alert('hello') };
fn.toString() // "function() { alert('hello') };"
So you can alert it:
alert(fn.toString());
You can log it to the js console:
console.log(fn.toString());
Or even write it to the page.
document.getElementById('someID').innerHTML = fn.toString();
However, this won't work for every function in the universe.
[].push.toString()
"function push() { [native code] }"
Some functions are not implemented with javascript, but in the compiled code of the browser or JS engine. For these environment provided functions, you will get this above less helpful output.
If you're not in strict mode you can go up the stack from something which was referenceable (i.e. a named function expression) using (non-standard) .caller
function getFunctionReference(callback) {
var ref = getFunctionReference.caller;
if (callback) callback(ref);
return ref;
}
Now you can do things like
(function () {
getFunctionReference(alert);
}());
// alerts the .toString of the IIFE
This only works for functions, you can't do this on top level code.
The best way to explore your code is actually with the Console, and you can use the debugger; statement or breakpoints to follow exactly what is happening and when.

Can a nested function be placed in the global scope of Javascript?

I have a situation where I'm trying to consolidate several Javascript files into one, and conditionally apply them. I don't want to modify the actual files. Is there a way I can wrap these files and call them on demand?
The catch is, some of these files have function xyz() {} in them. So, wrapping them with if (false) { function xyz() {} } makes bad things happen.
For example, if this is my code...
if (includeFile) {
/* The file */
function foo() {}
/* The file */
}
The problem becomes that Chrome will see foo() and place it in the global scope even if includeFile is false.
The easy solution would be to modify it to be var foo = function() {} but I can't modify these files.
I also have a general concern about running eval() on these functions since they are fairly huge. (Think jQuery wrapped in a function. If this isn't a problem then maybe eval is the answer?)
I was hoping I could nest functions and pass window in as the scope, but tried it on jsFiddle and it didn't seem to work.
(function() {
function foo() {
alert('it works');
}
}).apply(window, []);
foo();
There are a few similar questions. But, none addressed the same situation that I have. Thanks.
Have you considered using a library like require.js? There are several libraries out there that can do this for you in a more elegant fashion.
If you don't want a dependency-loading library, but you're using jQuery or some similar library, you can load scripts conditionally using an AJAX request (in jQuery, you'd use the script dataType). This is far better than a simple eval(), but less robust when you're trying to manage a series of dependencies.
Another option here, if you want to simply concatenate everything, is to wrap each file in an anonymous function and then assign the necessary elements to the window object, placing them in the global scope:
(function(window) {
/* file 1 here */
function xyz() {
// etc ...
}
/* end file 1 */
// now selectively choose what you want to be
// in the global scope
window.xyz = xyz;
}(window));
xyz();
This requires more work for you, however, to identify what you want to be available globally. Note that it's note necessary to pass window in as an argument to the anonymous function, but it's not a bad idea if you're going to be be referring to it multiple times (this speeds up references and allows for variable-name munging during code compression).

Self invoking functions javascript

I wrote a self invoking function in both firefox and chrome it it wouldn't invoke.
I wrote something to the effect of
(function () { alert("THE"); })();
do self invoking functions not work in current browsers?
I did include all essential tags and all other code works on the page
"Self-invoking functions" are not really a part of javascript, it's just a term that people are calling a specific pattern of code (like AJAX, etc.); these patterns should work anywhere that javascript works.
What you're calling a "self-invoking function" is just creating an anonymous function and immediately calling it (as opposed to say storing it in a var, as an object value, as a function param, etc.).
That is, the following are basically the same:
var f = function(){...}; f()
and
( function(){...} )()
So because your 'self-invoking function' is a basic part of javascript, there is no possible way it's not working unless the insides aren't working or your environment is messed up. You could copy-paste your code onto a new blank page, and it would work fine. Something else must be going wrong:
Check your errors in your dev console. Specifically, check to make sure you don't have a syntax error or that there isn't some weird thing going on with the webpage you're testing it on (e.g. if you somehow redefine alert...).
I had this issue with a self invoking function which produced this error...
Uncaught TypeError: object is not a function
The problem was caused by not having a semi colon ending the line before the opening bracket
That function works. Javascript supports functional programming, so for a browser not to run that code, even for a very old browser that would be absurd. Are you sure that statement is being reached? Try debugging javascript that occurs before that statement.
<script type="text/javascript">
(function() {
alert('Hello World!');
})();
</script>
Works in every browser I have installed on this machine.
This function definitely works. I would check your browser's console for any js errors in your page. Perhaps you could try to put a simple console.log function at the beginning of your script to see if any JavaScript is being called in the first place.
This self invoking function with return value will work in all current browsers(Safari, Chrome and Firefox) without issue. This function executes immediately, automatically and anonymously.
<script type="text/javascript">
alert((function(){
return("Hello World");
})());
</script>
I had a similar problem. I'm mentioning it below.
I couldn't run this self-invoking function on any browser
(function myfunc() {
var x = 34;
console.log(x);
})();
but whenever I added window.onload like below, it worked fine:
window.onload = (function myfunc() {
var x = 34;
console.log(x);
})();

Categories

Resources