I have many js methods that uses global variables like:
function DoSomething() {
var val=$('#'+clientId).val();
.
.
.
}
DoSomething uses clientId variable. The problem is that clientId is not always declared and therefore I get an exception of undeclared variable.
I have many places like this and add if (typeof clientId == "undefined") check everywhere is a lot of work and code duplication (duplication of the check). Is there I can workaround it? for example use a method that returns null if the variable is not declared? (In such way I can control on the return value in case of an undefined for example)
It seems to me that your code is just busted if you have code paths that attempt to use a global variable before it is defined. Either you need to give it a default value, you need to reorder the loading or execution of your code or you need to prevent code from running when your environment hasn't been initialized.
It is possible to initialize a variable if and only if it hasn't already been defined like this:
var clientId = clientId || "foo";
You could put this at the top of any module that uses it. This would initialize it with whatever value you want if and only if it wasn't already initialized.
You could also build yourself an accessor function that you would use instead of directly accessing the variable like this:
// put this somewhere early in the JS loading process
function getClientId() {
if (typeof window.clientId !== "undefined") {
return(window.clientId);
} else {
return("foo"); // whatever default value you want to return here
}
}
// use it like this:
function DoSomething() {
var val=$('#'+getClientId()).val();
.
.
.
}
Or, you can make a global function that will test it:
function isClientId() {
return(typeof window.clientId !== "undefined");
}
// use it like this:
function DoSomething() {
if (isClientId()) {
var val=$('#'+clientId).val();
.
.
.
}
}
Just an idea: all variables are properties of a namespace, up to the global namespace (in a browser, that's window). A property that's not assigned evaluates to undefined. So if you want to know if a variable is assigned, you can use if (property in namespace). If it concerns a global variable in a browser: if (clientId in window). Now you can make a function out of that:
function exists(label, namespace){
namespace = namespace || window;
return namespace[label] || false;
}
// possible usage
function DoSomething() {
var val=$('#'+( exists('clientId')||0) ).val();
// ...
}
Global variables are evil and are to be avoided if at all possible.
In the example you give, it would be much better to declare client ID as a parameter, like so:
function DoSomething(clientId) {
var val=$('#' + clientId).val();
.
.
.
}
This way, you are not affected by issues with global variables and there are no side effects (value changes caused by other methods) to worry about.
Good luck!
try :
var isExists =clientId || false;
but be careful
if ClientId==0 it will show you false.
I use:
if (typeof (foo) != 'undefined')
alert ('foo is defined');
If the variable itself is declared (as opposed to just having an undefined value), then you can simply use ( clientId || 'default value' ). This requires that you have var clientId; or something similar in the global scope (which is bad practice, BTW).
If you do not have a guarantee that clientId has been declared somewhere, then using the above construct will still throw an undefined variable error. In that case, you can use this: ( typeof clientId == 'undefined' ? 'default value' : clientId ).
While i like the answers, I go the simple way... Just declare var clientId; on top of your script. If you don't pass it any values then :
var clientId;
if(!clientId){
//will reach here cause declared but with no value
}
but
var clientId;
clientId = 132;
if(!clientId){
}else{
//will reach here cause it has a value
}
so
function DoSomething() {
if(clientId){
Would work
Related
Sorry for the noobish question, but nothing works for me today.
I'm creating a Phonegap application and have intergrated PushWoosh API into my app. And on receive push notification I want to run my previous functions again, so the data will be updated.
Pushwoosh has JS function like this:
document.addEventListener('push-notification',
function(event) {
var title = event.notification.title;
var userData = event.notification.userdata;
var notification = event.notification;
if (typeof(userData) != "undefined") {
console.warn('user data: ' + JSON.stringify(userData));
}
var object = JSON.parse(notification.u);
window.runPushFunctions(object.active, object.open); //Runs a jQuery function I have created..
}
);
Now window.runPushFunctions looks like this:
$(document).ready(function() {
window.runPushFunctions = function(active, open) {
if (active != null || active != undefined) {
$('.hubs-page').removeClass('hubs-active').hide().eq(active).show().addClass('hubs-active');
}
if (open == 2) {
$('html').addClass('hubs-opening');
}
//Trying to run functions from jQuery file that will get data from database and so on..
received();
sent();
checkFriends();
};
});
But I can't for some reason not run received(), sent(), checkFriends().
These functions is set like this in their own files like this:
(function($) {
'use strict';
function checkFriends () {
$.getJSON('url',function(data){
$.each(data,function(index,value){
//Do something with value
});
});
}
Im including files in this order:
file.js -> received(); sent();
file.js -> checkFriends();
file.js -> pushnotifications
Any help will be gladly appreciated
As the other answer here says, you are scoping your method definitions so they are not accessible anywhere outside the containing method.
(function($) {
This is a method definition. Any variables or functions non-globally declared within it cannot be accessed outside it. Therefore, you need to define the functions somewhere else or make them global for them to be accessible.
If you go for defining them somewhere else, you can simply move the function definitions to the top of the same file, outside of the (function($) {})() scope.
If you go for global definitions instead, you need to change the methods' defining lines slightly: instead of
function foo() { }
you need
window.foo = function() { }
This assigns an anonymously declared function to an object in the window scope, which is globally accessible. You can then call it using
window.foo();
or simply
foo();
since it is in the window scope.
I'm not exactly sure I'm understanding your question, but it looks to me like you are defining the function checkFriends inside of a function scope. If you need access to that function definition, you would need to declare it on an object that can be referenced from the global scope. Obviously the easiest way to do that would be to attach it to the window, though there are plenty of reasons not to do that.
window.checkFriends = function(){//code that does stuff};
Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.
This is a .html page.
Kendo Auto Complete has a SELECT functionality:
select: function(e)
{
valid = true;
if (e.item == null)
{
return;
}
var DataItem = this.dataItem(e.item.index());
nameId = DataItem.NameId;
personId = DataItem.PersonId;
}
Basically what the above does is captures some variable values for me.
This is working fine.
The issue is, I want to use the variables nameId and personId in some other function and event later.
What would be the correct way to "save" these variables?
These variables will be used as parameters on a POST request later.
Store locally on client side:
localStorage.setItem("nameId",nameId);
localStorage.setItem("personId",personId);
Retrieve their values:
nameId=localStorage.getItem("nameId");
personId=localStorage.getItem("personId");
you can use global variables (although this method should only be done as a last resort)
otherwise, javascript is going to assume the scope of your variables to last only the length of the function. If you want the scope to extend beyond the function, then declare them outside the function like so:
var date_item = null
function doSomething(){
date_item = b
}
function doSomethingElse(){
alert(data_item)
}
to use a global variable, just dont use the prefix "var" in front of your variable declaration
var date_item = null // local
date_item = null // global
$(".app-launch").on("click", function () {
var appId = this.id;
// Check if Function is running.
if (typeof eval('$' + appId).start == 'undefined') {
eval('$' + appId).start();
}
}
The eval just causes it to come back and say $XXXXXX is not defined and kills the java-script execution. Is there anyway to prevent it from killing the execution and continuing? This function is either launching the application or loading the javascript first and then launching the application, so this check is there to determine if the javascript has already been loaded.
Try this
eval('$("' + appId + '"')
First, stop using eval. If you want dynamically namable variables, use an object.
Then you can just test the type of the object before you try to access its start property.
var objects = {};
var appId = "thing";
objects[appId] = { start: foo; }
if (
typeof objects[appId] !== 'undefined' &&
typeof objects[appId].start === 'function'
) {
objects[appId]();
}
If you are trying to retrieve a global variable, just use the associative array syntax window['$'+appId]
Also, the reason your code is breaking is because you are checking if the start method is defined, whereas it is $XXXXXX that does not exist. Check if $XXXXXX exists before referencing the method. Also, you are calling the method if it is not defined, which makes no sense.
Also eval.
Here is a jsfiddle that shows what is wrong. Here is a fixed version.
I'm developing a javascript application that consists of many objects and functions (object methods). I want to be able to log many events in the life cycle of the application. My problem is that inside the logger I want to know which function invoked the log entry, so I can save that data along with the log message. This means that every function needs to somehow be able to reference itself, so I can pass that reference to the logger.
I'm using javascript strict mode, so using arguments.callee inside the function is not allowed.
Here's a very simplified code sample you can run. I'm just using here alert instead of my logger for simplicity.
(function(){
"use strict";
window.myObject = {
id : 'myObject',
myFunc : function(){
alert(this.id); // myObject
alert(this.myFunc.id); // myFunc - I don't want to do this. I want something generic for all functions under any object
alert('???') // myFunc
alert(arguments.callee.id); // Will throw an error because arguments.callee in not allowed in strict mode
}
}
myObject.myFunc.id = 'myFunc';
myObject.myFunc();
})();
In the first alert - this related to myObject and not to myFunc
In the second I alert - I referenced the function by its name, which I don't want to do, as I'm looking for a generic way to reference a function from within its own implementation.
The third alert - open for your ideas.
The fourth alert - would have worked if I didn't "use stict";. I want to keep strict mode since it provides better performance, and constitutes good coding practice.
Any input will be appreciated.
If you're not familiar with "strict mode", this is a good place read about it:
JavaScript Strict Mode
Here's a very hacky way of doing it:
(function(){
"use strict";
window.myObject = {
id: 'myObject',
myFunc: function () {
// need this if to circumvent 'use strict' since funcId doesn't exist yet
if (typeof funcId != 'undefined')
alert(funcId);
},
myFunc2: function () {
// need this if to circumvent 'use strict' since funcId doesn't exist yet
if (typeof funcId != 'undefined')
alert(funcId);
}
}
// We're going to programatically find the name of each function and 'inject' that name
// as the variable 'funcId' into each function by re-writing that function in a wrapper
for (var i in window.myObject) {
var func = window.myObject[i];
if (typeof func === 'function') {
window.myObject[i] = Function('var funcId = "' + i + '"; return (' + window.myObject[i] + ')()');
}
}
window.myObject.myFunc();
window.myObject.myFunc2();
})();
Essentially, we are circumventing the 'use strict' declaration by recompiling each function from a string after we've found out that function's name. To do this, we create a wrapper around each function that declares a string variable 'funcId' equal to our target function's name, so that the variable is now exposed to the function within through closure.
Eh, not the best way to do things, but it works.
Alternatively, you can simply call a non-strict function from within:
(function(){
"use strict";
window.myObject = {
id: 'myObject',
myFunc: function () {
alert(getFuncName())
},
myFunc2: function () {
alert(getFuncName());
}
}
})();
// non-strict function here
function getFuncName(){
return arguments.callee.caller.id; // Just fyi, IE doesn't have id var I think...so you gotta parse toString or something
}
Hope that helps.
I don't think what you want to do (finding the name of the current function) is very easy to do. You might want to look into adding a preprocessing step (like is done for things like __line__ in C) but perhaps just a little OO/currying magic does the trick:
function logger(id){ return function(msg){
return console.log(id, msg);
};}
window.myObject = {
id : 'myObject',
myFunc : function(){
var log = logger('myFunc');
log(1); //prints "Myfunc, 1"
log(2); //prints "Myfunc, 2"
}
};
This is kind of a cop out but is very simple and can be reasonably mantainable if you just remember to keep the ids and function names in track.
myFunc : function _myFunc(){
alert(_myFunc); // function
}
Name your functions and reference them directly
To solve your logging purpose, use real sensible unique logging messages. If you want line information then throw an exception.