Turning single values and arrays into arrays including zeros as single value - javascript

While I was searching for a good way to check if a function variable is an array or a single variable and then turn both into arrays for further processing, I came across this post.
The answer provided by #VoteyDisciple
var eventsArray = events ? [].concat(events) : [];
works great for me until events is a single variable with a value of zero. In that case, eventsArray will be empty. Here is my entire code:
var eventsArray = [];
if (!(Array.isArray(events))) {
eventsArray = events ? [].concat(events) : [];
} else {
eventsArray = events;
}
I have tried to make another if-statement before the else line to catch this special occasion. But that ends up in a mess for the rest of the code and I doubt it's very elegant. Therefore I wonder if it is possible to change this line:
eventsArray = events ? [].concat(events) : [];
in a way so that if events is a single variable with a value of zero, this line will also turn this occasion into an array with a single element and a value of zero?
For understanding things better, I also want to ask: Why does this line of code "lose" the zero but works great with any other single value?

It's much simpler:
eventsArray = Array.isArray(events) ? events : [events];
The reason you lose the zero is because zero is falsey in a boolean context like the conditional operator. You'll also lose null and empty strings.

Related

Why is this JavaScript object method returning 'not a function' method?

this.breakintoletters=()=>
this.lengthi!==0?(this.title2=this.title,this.title2.split(),this.title2.
map((x)=>this.arol.push(new letter(x))))
:!!false
So basically this is the code. It's supposed to break the string into letters and then push pertinent objects into an array..
Checks for the length of the string, if not 0 proceeds, returns an errors where MAP function is at...) TypeError telling me it's not a function. Editor is not showing errors. Would appreciate help
I suggest to use a different approach by checking this.lengthi in advance and return either false, or later the mapped length of the pushed values.
this.breakintoletters = () => {
if (!this.lengthi) return false;
this.title2 = this.title;
// this.title2.split(); the result is not taken, not even splitted
return this.title2.map(x => this.arol.push(new letter(x)));
};
You're not assigning splited value back to this.title2 and than using map on this.split2 which is a string
this.breakintoletters=()=>
this.lengthi ? (this.title2=this.title,
this.title2=this.title2.split(),
this.title2.map((x)=>this.arol.push(new letter(x))))
:false
IMO you should try to make your code consice only upto a point where it stays readabale you can simply it in following manner
this.breakintoletters = ( ) => {
if(this.lengthi === 0 ) return false;
this.title2=this.title;
this.title2=this.title2.split();
return this.title2.map((x) => this.arol.push(new letter(x))))
}
(this.title2=this.title, this.title2.split(), this.title2.
map((x)=>this.arol.push(new letter(x))))
Is this.arol the name of an array?
Try restructuring it to be:
(this.title.split().map((x) => this.arol.push(new letter(x)))
Methods like split() join() map() etc can be chained together.
I would rethink using the map function here though and the ternary which other commenters covered above. I mean it works technically, but if the goal is to iterate through the string in order to push certain values, it'd be better to use a for loop. Map functions are more when you want to iterate in order to apply the same specified method to each individual character
Also this is just a formatting thing but it makes it a lot easier to read and understand your code when you have some spaces between variables and operators, and choosing variable names that make sense for what you are doing (this.bookLength, this.reverseAr), or at least using the generic this.array or this.arr It makes it easier to ask questions like this because you'll get less clarifying questions about typos, and also if you are ever planning to work on a larger code base it's important to write clean code that is understandable to someone who doesn't know you

Splitting string results in infinite loop

I need to split this string and loop through the resulting array. However, even though my result string array has only 3 items, my loop goes to infinity.
I am probably missing something, but I can not see it at this point.
Here is the code:
CustomizeDashboardService.getCustomizedDashboard().then(function (res) {
console.log(res);
var sensors = res.sensor.split(',');
var devices = res.uuid.split(',');;
console.log("CS: S",sensors) // I Can see these 2 arrays have only 3 items each,
console.log("CS: D",devices) // but when it goes into my for loop, it iterates to indefinite
for(i=0;i<devices.length-1;i++){
console.log("girdi") // I see this is logging more than 1000 times
var index = findIndex(devices[i]);
var obj = {
device:self.deviceList[index],
sensor: sensors[i]
}
self.customizedSensors.push(obj);
}
console.log("customized sensors",self.customizedSensors);
})
Your loop has for(i=0;i<devices.length-1;i++) which means the iteration variable is not locally scoped. If somewhere else the i value is changed then it can cause issues. As a matter of habit, always var your iterator variable unless you have a very specific reason not to (such situations do exist but are fairly rare). To avoid other issues I would recommend looking through all of your code and making sure you have the var in there.

JavaScript variable assignment with OR vs if check [duplicate]

This question already has answers here:
What does the construct x = x || y mean?
(12 answers)
Closed 6 years ago.
In JavaScript I recently realized you could use the OR || logical operator for assignment, and I want to know if it's considered bad practice.
In particular I have some functions that have optional array input, if the input is null or undefined I should just set it to an empty array [], if it has content it should take the content.
I found that using the assignment using the OR operator handles that perfectly in a single line, it's clean. However, it feels like the kind of thing that might be considered bad practice, or may have some horrible pitfalls I'm not considering.
Another approach is a simple if check, which is fairly safe in general.
I want to know if using the || approach seen below has any pitfalls I'm not considering, although it works in this scenario I would appreciate knowing if it works well to keep using this in the future, or to stop using it altogether.
https://jsbin.com/nozuxiwawa/1/edit?js,console
var myArray = ['Some', 'Strings', 'Whatever'];
// Just assign using OR
var pathOne = function(maybeAnArray) {
var array = maybeAnArray || [];
console.log(array);
}
// Assign using IF
var pathTwo = function(maybeAnArray) {
var array = [];
// Covers null and undefined
if (maybeAnArray != null) {
array = maybeAnArray;
}
console.log(array);
}
console.log('Path one:');
pathOne(myArray); // ['Some', 'Strings', 'Whatever']
pathOne(null); // []
console.log('\nPath two:');
pathTwo(myArray); // ['Some', 'Strings', 'Whatever']
pathTwo(null); // []
IMHO the use of the OR || for the purposes of assignment is perfectly valid and is good practice. We certainly use it in our projects and I've seen it used in lots of 3rd party projects that we use.
The thing you need to be aware of is how certain JavaScript objects can be coerced to be other values. So for example, if you're ORing values such as "", false or 0 then they are treated as false... this means that when you have the following:
function f(o) {
var x = o || -1;
return x;
}
Calling:
f(0)
...will return -1... but calling
f(1)
Will return 1 ... even though in both cases you passed a number - because 0 is treated as false -1 is assigned to x.
...that said, as long as you're aware of how the OR operator will treat the operands that you use with it - then it is good JavaScript practice to use it.
i prefer the first option, it's clear for my eyes, but when i need to share my code with others will think about to use second, will be more clear for any.
Now i'm using sonar, and prefer the second option too, will more easy to comprend for machine in inegration works.
Last idea is to use
if(maybeAnArray !== void(0))
Two reasons:
use cast and type conditionals
void(0) will works same for all browsers
Expect it helps yopu
When given the option, I prefer concise code (which must still be readable).
I would say || is common enough that it is considered good practice. Once one has seen it a few times it reads just fine.
In my opinion there are few reasons why you should rather use the second option:
First of all it's much more readable - new developers that are still learning can have problems with understanding notation like var myArray = someArrayArg || [];
If you are using some kind of code checkers like JSLint, they will return warnings and/or errors like Expected a conditional expression and instead saw an assignment. for the statement with var myArray = someArrayArg || [];
We already have something like var myArray = someArrayArg ? someArrayArg : []; that works pretty well

How to detect when a property is added to a JavaScript object?

var obj = {};
obj.a = 1; // fire event, property "a" added
This question is different from this one, where ways to detect when an already declared property is changed, being discussed.
this is possible, technically, but since all current JS implementations that I know of are single threaded it won't be very elegant. The only thing I can think of is a brute force interval:
var checkObj = (function(watchObj)
{
var initialMap = {},allProps = [],prop;
for (prop in watchObj)
{
if (watchObj.hasOwnProperty(prop))
{//make tracer object: basically clone it
initialMap[prop] = watchObj[prop];
allProps.push(prop);//keep an array mapper
}
}
return function()
{
var currentProps = [];
for (prop in watchObj)
{
if (watchObj.hasOwnProperty(prop))
{//iterate the object again, compare
if (watchObj[prop] !== initialMap[prop])
{//type andvalue check!
console.log(initialMap[prop] + ' => ' watchObj[prop]);
//diff found, deal with it whichever way you see fit
}
currentProps.push(prop);
}
}
//we're not done yet!
if (currentProps.length < allProps.length)
{
console.log('some prop was deleted');
//loop through arrays to find out which one
}
};
})(someObjectToTrack);
var watchInterval = setInterval(checkObj,100);//check every .1 seconds?
That allows you to track an object to some extent, but again, it's quite a lot of work to do this 10/sec. Who knows, maybe the object changes several times in between the intervals, too.All in all, I feel as though this is a less-then-ideal approach... perhaps it would be easier to compare the string constants of the JSON.stringify'ed object, but that does mean missing out on functions, and (though I filtered them out in this example) prototype properties.
I have considered doing something similar at one point, but ended up just using my event handlers that changed the object in question to check for any changes.
Alternatively, you could also try creating a DOMElement, and attach an onchange listener to that... sadly, again, functions/methods might prove tricky to track, but at least it won't slow your script down as much as the code above will.
You could count the properties on the object and see if has changed from when you last checked:
How to efficiently count the number of keys/properties of an object in JavaScript?
this is a crude workaround, to use in case you can't find a proper support for the feature in the language.
If performance matters and you are in control of the code that changes the objects, create a control class that modifies your objects for you, e.g.
var myObj = new ObjectController({});
myObj.set('field', {});
myObj.set('field.arr', [{hello: true}]);
myObj.set('field.arr.0.hello', false);
var obj = myObj.get('field'); // obj === {field: {arr: [{hello: false}]}}
In your set() method, you now have the ability to see where every change occurs in a pretty high-performance fashion, compared with setting an interval and doing regular scans to check for changes.
I do something similar but highly optimised in ForerunnerDB. When you do CRUD operations on the database, change events are fired for specific field paths, allowing data-bound views to be updated when their underlying data changes.

Why is my jQuery each loop not adding values correctly?

I am trying to get the values of several fields & add them together & in my testing I am having problems. I have this code:
var count;
function calculate() {
// Fix jQuery conflicts
jQuery.noConflict();
count = 0;
jQuery('.calculate').each(function() {
var currentElement = jQuery(this);
var value = currentElement.val();
var count = count + value;
alert(count);
});
}
I enter in the value of "9" in my first field & when the first alert triggers I get "undefined9"; all the other values are currently set to "0"; when it triggers again I always get "undefined0".
Why am I getting the "undefined" bit & why is it only returning the value of the current field & not adding them together?
You are dimensioning the count value inside the loop, essentially setting it to undefined first in each iteration.
You want to remove the var within the loop. This way, it doesn't have scope to the anonymous function and JavaScript will look at the parent function for its declaration.
It may also be a good idea to parseInt(count, 10) the number first, because JavaScript overloads the + operator to mean arithmetic addition and string concatenation, and you wouldn't want count to be "0something".
Finally, count += value is easier to read :)
You're accidentally re-declaring count:
var count = count + value;
should be:
count = count + value;
The count declared in the inner-most scope (that of calculate) will hide the other one (this is called "shadowing" of variables).
The reason you get "undefined9" is because the default value of the newly-declared count variable is undefined; when you add to it, it sees an undefined value on the left, and a number on the right, and decides that string concatenation is the best way to perform the addition, resulting in the string "undefined9".
It has to guess at your intended meaning since + is overloaded to mean both numerical addition and string concatenation; in this case, it guesses wrong.
You're defining count in two different scopes - the calculate function, and then in the function that each is using. You may want to have the second count be named something else, or at least don't redeclare it.

Categories