How to define a variable that is undefined? - javascript

I have the following code:
if (!config.callers[uID].calls) {
console.log(config.callers[uID].calls);
config.callers[uID].calls = 0;
saveConfig();
console.log(config.callers[uID].calls);
}
Where I have a JSON file that is called config, and has a property callers which is a collection of user IDs, and each one has a property calls. saveConfig() is a function that saves the config file.
As you can see, I am checking if the calls property is undefined, and if true then it defines it at 0. I also tried defining it to different stuff but it didn't seem to work. It just stays undefined.

Try
if(!config.callers.hasOwnProperty("uID")) {
console.log(config.callers);
config.callers[uID] = {};
config.callers[uID].calls = 0;
saveConfig();
console.log(config.callers[uID].calls);
} else if(!config.callers[uID].hasOwnProperty("calls")) {
console.log(config.callers[uID]);
config.callers[uID].calls = 0;
saveConfig();
console.log(config.callers[uID].calls);
}

Related

Calling a method on every instance of a class in Javascript?

I am trying to call a class' method on every instance of that class.
Currently, I have all of my classes stored in an array, called checkers[]
I loop through every instance of the class Checker() using this for loop:
this.drawCheckers = function() {
for(var checker in this.checkers) {
checker.draw();
}
}
When I run the code, I get the error:
localcheckers.js:57 Uncaught TypeError: checker.draw is not a function
How would I fix this?
In your for...in loop, the value stored in checker is not the property in this.checkers, but the property name.
What you need to do is access the property then call draw on it.
this.drawCheckers = function()
{
for(var checker in this.checkers) {
this.checkers[checker].draw();
}
}
See a working example here:
https://jsbin.com/fezixaboso/edit?js,console
call draw() only if checker is an instance of Checker
this.drawCheckers = function() {
for(var i = 0; i < this.checkers.length; i++) {
if(this.checkers[i] instanceof Checker)
this.checkers[i].draw();
}
}

Node.JS Global Variable Not Staying Updated

I have a global object variable set called _storage. It looks like this:
_storage = {
test : {
}
};
When a user sends a request to add their info to the "test" object inside of storage, it's supposed to set _storage.test[1] = true; for example.
After it sets that, I did this to see what the variable looked like:
console.log(_storage.test); and it outputted the correct response:
{ '1' : true }
All seems perfect, until the user sends a request to get all the current items in the test object. This is where the problem is. The variable seems to empty itself and go back to an empty object {}.
The user sends the request to see what's inside of test after setting the data in test, so it can't be an issue caused by the user requesting to see the data before even setting it. This is done inside two separate modules, one sets the data and another one gets the data (the two modules aren't just for that only, obviously) but the _storage variable is global and shouldn't be affected by two separate modules.
Here's an example of how it goes down:
User sends request to set 1 = true inside of _storage.test, making _storage.test[1] = true;
_storage.test is now { test : { '1' : true } } according to console.log
User sends request to view all data from _storage.test
_storage.test is {} according to console.log, as if it isn't staying set
Here's the code that I use to Get, Set, and Remove the data:
exports.GetUserData = function () {
return global._storage.test;
};
exports.RemoveUserData = function (uid) {
delete global._storage.test[Number(uid)];
};
exports.AddUserData = function (uid) {
global._storage.test[Number(uid)] = true;
};
Ok, so I think you're not showing all your code, but here's what I did which worked:
// index.js
'use strict';
global._storage = global._storage || {};
global._storage.test = global._storage.test || {};
exports.GetUserData = function () {
return global._storage.test;
};
exports.RemoveUserData = function (uid) {
delete global._storage.test[Number(uid)];
};
exports.AddUserData = function (uid) {
global._storage.test[Number(uid)] = true;
};
// other.js
'use strict';
global._storage = global._storage || {};
global._storage.test = global._storage.test || {};
exports.GetUserData = function(){
return global._storage.test;
}
And then I ran this from my repl:
> var it = require('./');
undefined
> var other = require('./other');
undefined
> it.AddUserData('1234');
undefined
> it.GetUserData();
{ '1234': true }
> other.GetUserData();
{ '1234': true }
>
So that works as designed. Thing is this... I've been working with node since 2009, and I've never felt the need to use global variables. I doubt your app needs it. So even though this'll work for you, I recommend you think of another way to do it.

Avoiding multiple load of javascript file

I add this snippet to each javascript file used in my asp.net web api application to avoid multiple load :
Fullcalendar.js
blog = {};
blog.comments = blog.comments || {};
blog.comments.debugMode = false;
blog.isFirstLoad = function (namesp, jsFile) {
var isFirst = namesp.jsFile.firstLoad === undefined;
namesp.jsFile.firstLoad = false;
return isFirst;
};
$(document).ready(function () {
if (!blog.isFirstLoad(blog.comments, "fullcalendar.js")) {
return;
}
});
Sometimes I get a weird exception
Uncaught TypeError: Cannot read property 'firstLoad' of undefined
I need to know :
Why this happens?
How can I fix it?
A couple of problems there.
First, you shouldn't be loading the file more than once in the first place, so it shouldn't be necessary to go through this business of trying to figure out whether you've loaded it.
But if you want to do that:
The first practical issue is that you're always doing this:
blog = {};
...which means if there's already a blog global, you're wiping out its value and replacing it with an empty object. If you want to use an existing global's value or create a new one, do this:
var blog = blog || {};
That seems odd, but since repeated var declarations are fine (and don't change the variable), that will use an existing one's value, or if there isn't one (or its value is falsey) it will create a new one and initialize it with {}.
Then, the line
namesp.jsFile.firstLoad = false;
...looks for a property called jsFile on namesp and assumes it's not null or undefined. It doesn't look for a property using the jsFile argument's value.
To do that, use brackets notation:
namesp[jsFile].firstLoad = false;
Even then, though, you're assuming it's not null or undefined, but it may well be. You probably just wanted:
namesp[jsFile] = false;
Or possibly:
namesp[jsFile] = namesp[jsFile] ||{};
namesp[jsFile].firstLoad = false;
That said, it seems really odd to use blog.comments to track whether JavaScript files have been loaded. If the file may have already been loaded, just this will do it:
var fullCalendarLoaded;
if (fullCalendarLoaded) {
// It's already loaded
} else {
// It isn't, but it is now
fullCalendarLoaded = true;
// ...do your init...
}
Or if you have several of these and want to use a single global for it:
var loadedScripts = loadedScripts || {};
if (loadedScripts.fullCalendar) {
// Already loaded
} else {
// Not loaded yet
loadedScripts.fullCalendar = true;
// ...do init...
}
Or if using the filename is important:
var loadedScripts = loadedScripts || {};
function firstLoad(filename) {
if (loadedScripts[filename[) {
return false;
}
// Not loaded yet, remember we've loaded it now
loadedScripts[filename] = true;
return true;
}
Then:
if (firstLoad("fullcalendar.js")) {
// First load, do init...
}
It's fairly straightforward:
On your initial run, you define
blog = {};
blog.comments = blog.comments || {};
blog.comments.debugMode = false;
In theory, this means that on some loads, blog is:
var blog = {
comments: {
debugMode: false
}
}
You then pass blog.comments into your function isFirstLoad as the namesp parameter. In that function, you do the evaluation:
namesp.jsFile.firstLoad === undefined;
Well, you never defined the jsFile property of blog.comments. This means it is undefined. Trying to access the property firstLoad of an undefined variable will give you your error
Uncaught TypeError: Cannot read property 'firstLoad' of undefined

Javascript Setter Being Bypassed

Say I have this code:
function test() {
this._units = {};
}
test.prototype = {
get units() { return this._units; },
set units(val) {
this._units = val;
for (var unit in this._units) {
if (this._units[unit] === 0)
delete this._units[unit];
}
}
};
Now, I can assign a unit via the following:
x = new test();
x.units['foo'] = 1;
This all works. However, when I do this,
x.units['foo'] = 0;
// x.units = { 'foo' : 0 }
It doesn't remove foo from the units as it should. How can I change this?
Thanks!
You cannot intercept when a property is created, you'd need a Proxy for that. Unfortunately, it is only a harmony draft and currently only supported in Firefox' Javascript 1.8.5.
Your setter only detects an assignment to x.units = {foo:1}, but not to x.units.foo. You could create setters for every property on the units objects that you know of, but you need an extra method to make them known in the first place (assuming you're not only assigning objects to x.units).
However, you might better not do this at all. A property that deletes itself when being set to 0 is very counterintuitive. Think of
x.units.foo = -1; x.units.foo += 2;
Would you expect this to do the same as
x.units.foo = -1; x.units.foo++; x.units.foo++;
? The second would yield NaN instead of 1.

how to get a property name which represent a function in JS

This is some JS code
var methodArr = ['firstFunc','secondFunc','thirdFunc'];
for(var i in methodArr)
{
window[methodName] = function()
{
console.log(methodName);
}
}
My problem is that how to get the name of a function in JS.
In JS, use this.callee.name.toString() can get the function name. But in this situation, it is a null value. How can i get the 'funName' string?
Sorry, I didn't make it clear.
I want to create functions in a for loop, all these functions has almost the same implementation which need its name. But others can call these functions use different name.I want to know what methodName function is called.
it seems a scope problem.
Try this:
var methodArr = ['firstFunc','secondFunc','thirdFunc'];
for(var i in methodArr) {
var methodName = methodArr[i]; // <---- this line missed in your code?
window[methodName] = (function(methodName) {
return function() {
console.log(methodName);
}
})(methodName);
}
window['secondFunc'](); // output: secondFunc

Categories

Resources