javascript hash values validation - javascript

I'm trying to give the same behaviour to 4 values in my hash array.
For example:
var array = {};
if (array[key].config.tmp == undefined) {
array[key].config.tmp = {}
}
if(array[key].config.tmp.tp1){
}
if(array[key].config.tmp.tp2){
}
if(array[key].config.tmp.tp3){
}
if(array[key].config.tmp.tp4){
}
Since tp1, tp2, tp3 and tp4 will have the same behaviour. I would like to simplify the validation.
Something like:
array[key].config.tmp.[tp1,tp2,tp3,tp4] is possible? Already tried. but it was
tp1,tp2,tp3 and tp4 may not exist(undefined). (tp1 and tp2 only sometimes).
Any advice so I won't duplicate code?
Thanks in advance

You could also use a filter on the array keys:
if ( ( array[key].config.tmp || {} ).keys().filter(
function(k) { return /^tp[1234]/.test( k ) }
).length ) )

use a short-circuit operator like ||. for instance, if you are checking for the existence of multiple properties, accessing a property which doesn't exist is falsy.
var c = a[key].config.tmp.a || a[key].config.tmp.b || .... || //default
In this example, c will hold the value of the first of these to evaluate to true. You could also include a "Default" value at the end if they all return false. Keep in mind that accessing a property of a property that doesn't exist is a type error however, so you must be sure that at least config.tmp exists. So you can replace your code with
if (a[key].config.tmp.a || a[key].config.tmp.b || ....) {
}

Related

What would be the most efficient way to check if a JavaScript variable is either falsey, or an empty array or object?

I have a use case where a function receives a variable which could be of various types, including an array or an object reference.
But I want to ignore any variables passed in which are falsey in the usual JavaScript senses, plus I want to treat empty arrays [] and empty objects {} as also being falsey.
I can see immediately there would be many ways to do this but I'm wondering what would be most efficient assuming a very modern JavaScript implementation and only vanilla JavaScript with no frameworks.
The obvious way is to check if it's an array or an object and check .length in the case of an array and Object.keys(x).length if it's an object. But considering that some other things which are already falsey are also typeof object and that empty arrays seem to behave either truthy or falsey depending on how you check, I'm betting that some ways are more efficient and probably more idiomatic too.
The following should match your criteria (Although it looks ugly).
if (
sth && // normal JS coercion
(!Array.isArray(sth) || sth.length) && // falsify empty arrays
(Object.getPrototypeOf(sth) !== Object.prototype || Object.keys(sth).length) // falsify empty objects
)
alert("pass");
Tests:
sth = []; // Don't Pass
sth = {}; // Don't Pass
sth = null; // Don't Pass
sth = false; // Don't Pass
sth = undefined; // Don't Pass
sth = ""; // Don't Pass
sth = [1]; // Pass
sth = { a: "" } // Pass
sth = new Date; // Pass
sth = "a"; // Pass
sth = function(){} // Pass
This checks if sth is truthy:
if(sth && (typeof sth !== "object" || Object.keys(sth).length))
alert("passes");
I use this al the time.
function IsEmpty(val){
return (!val || val == "" || (typeof(val) === "object" && Object.keys(val).length == 0) || val === [] || val === null || val === undefined);
}
Examples that pass
if(IsEmpty(false)){console.log("pass");}
if(IsEmpty("")){console.log("pass");}
if(IsEmpty([])){console.log("pass");}
if(IsEmpty({})){console.log("pass");}
if(IsEmpty(null)){console.log("pass");}
if(IsEmpty()){console.log("pass");}
Examples that fail
if(IsEmpty(true)){console.log("fail");}
if(IsEmpty("not null")){console.log("fail");}
if(IsEmpty([1])){console.log("fail");}
if(IsEmpty({"a":1})){console.log("fail");}
//!IsEmpty means is not empty
if(!IsEmpty(false)){console.log("fail");}
if(!IsEmpty("")){console.log("fail");}
if(!IsEmpty([])){console.log("fail");}
if(!IsEmpty({})){console.log("fail");}
if(!IsEmpty()){console.log("fail");}

Is there a way to simplify conditionally adding values to an object with node.js?

I have a node.js script where I'm adding keys to an object if either a local or global value exists. I feel as though there should be a good way to simplify this, but I'm not seeing it. Is there a way to make this code less verbose:
var object = {
defaultKey: defaultValue
};
// Add some conditional keys based on local and global settings
// With local settings taking precedence
if (local.firstSetting || firstSetting) {
entry.firstSetting = local.firstSetting || firstSetting;
}
if (local.secondSetting || secondSetting) {
entry.secondSetting = local.secondSetting || secondSetting;
}
if (local.thirdSetting || thirdSetting) {
entry.thirdSetting = local.thirdSetting || thirdSetting;
}
I've thought about adding all the keys to the object and just assigning them a value of local.thirdSetting || thirdSetting, but I don't think it would be smart to potentially have keys with an undefined value.
There is shared functionality here which can be refactored into a function.
function getSetting(name) {
var setting = local[name] || globals[name] || entry[name];
if(setting) {
entry[name] = setting;
}
}
getSetting('firstSetting');
getSetting('secondSetting');
getSetting('thirdSetting');
Modification of Jaromanda X's anwer:
var t;
if( t = local.firstSetting || firstSetting ) entry.firstSetting = t;
if( t = local.secondSetting || secondSetting ) entry.secondSetting = t;
if( t = local.thirdSetting || thirdSetting ) entry.thirdSetting = t;
You could use a module like xtend.
It allows you to use an arbitrary number of objects that will be merged into one object. Consider that the right-most object takes precedence over all the others.
This requires your global variables to be grouped into a single object, which is probably a good idea anyway.
What I'm doing now is this:
var pick = require('lodash.pick');
var identity = require('lodash.identity');
var object = pick({
defaultKey: defaultValue
firstSetting: local.firstSetting || firstSetting,
secondSetting: local.secondSetting || secondSetting,
thirdSetting: local.thirdSetting || thirdSetting
}, identity);
This will filter all undefined values (or falsy values to be precise) from the object.

Changing match to allow null input in javascript

I have some inherited code which is causing problems in Safari.
The problem comes from a few lines in the code that do things like this:
if ( ... && $("#element1").val().match(/regex/) && ...)
The javascript itself is programmatically generated.
The problem is that sometimes that $("#element1").val() returns null and I can't easily put a typeof check before it, because it needs to treat null as empty string.
The easiest (and manageable) solution would be either to create a nullmatch function and call that instead or to override the .match function itself. The new function would then check for null first and (if it is null) pass empty string to match instead of null.
I am not sure how to do either, or which would be best.
It would be better to either replace, or add to it (e.g.
$("element1").val().nullmatch(/regex/) or
$("element1").val().nullToEmpty().match(/regex/)
That isn't really possible, because .nullmatch or .nullToEmpty would need to be a method on a possibly null value.
If you really want to write in this fashion, or it's easier for your backend to generate, then you could write a mini-plugin:
$.fn.valNullToEmpty = function() { return this.val() || ''; }
$("element1").valNullToEmpty().match(/regex/)
You can use the || operator:
if ( ... && ($("#element1").val() || "").match(/regex/) && ...)
Basically, foo || "" will return foo if it's truthy, or the empty string if foo is falsy (false, undefined, null, empty string, +0, -0 or NaN).
How about...
function nullString(str) {
if (str === null) {
return "";
else {
return str;
}
So your if statement could become
if ( ... && nullString($("#element1").val()).match(/regex/) && ...)
The jQuery docs for val() state that it returns null when the element is select and no options are selected.
So using valHooks may help
var originalSelectHook;
if ($.valHooks.select) {
originalSelectHook = $.valHooks.select.get;
}
$.valHooks.select = {
get: function(elem) {
var index = elem.selectedIndex;
if (index == -1 || elem.options[index].disabled) {
return "";
}
else {
return originalSelectHook(elem)
}
};
Code assumes that there is a existing hook for select

In JavaScript, is there an easier way to check if a property of a property exists?

Is there an easy way to natively determine if a deep property exists within an object in JavaScript? For example, I need to access a property like this:
var myVal = appData.foo.bar.setting;
But there is a chance that either foo, foo.bar, or foo.bar.setting has not been defined yet. In Groovy, we can do something like this:
def myVal = appData?.foo?.bar?.setting
Is there a similar way to do this in JavaScript, without having to write a custom function or nested if statements? I've found this answer to be useful, but was hoping there was a more elegant and less custom way.
I find this very convenient:
var myVal = (myVal=appData) && (myVal=myVal.foo) && (myVal=myVal.bar) && myVal.settings;
If a property exists, the next part of the sequence will be attempted.
When the expression before && evaluates to false, the next part of the expression will not be checked. If either of myVal.appData.foo.bar.settings is not defined, the value of myVal (undefined( will evaluate to false.
Sorry, it's not great:
var myVal = appData && appData.foo && appData.foo.bar && appData.foo.bar.setting;
Another option:
try {
var myVal = appData.foo.bar.setting;
} catch (e) {
var myVal = undefined;
}
The . operator is not really intended for accessing objects like this. Probably using a function would be a good idea.
The optional chaining operator (?.) was introduced in ES2020. Now, you should be able to write:
const myVal = appData?.foo?.bar?.setting
I find other approaches a bit immense. So, what would be the major drawback of the following approach:
// Pass the path as a string, parse it, and try to traverse the chain.
Object.prototype.pathExists = function(path) {
var members = path.split(".");
var currentMember = this;
for (var i = 0; i < members.length; i++) {
// Here we need to take special care of possible method
// calls and arrays, but I am too lazy to write it down.
if (currentMember.hasOwnProperty(members[i])) {
currentMember = currentMember[members[i]];
} else {
return false;
}
}
return true;
}
Basically, we define a method on the object (not necessarily) and that method takes the path to a nested object and returns existence confirmation, likeappData.pathExists("foo.bar.setting");
EDIT:
Check object[prop] == undefined is not semantically correct since it will return false even if the property is defined although its value is undefined; that is why I use hasOwnProperty to check is the property defined. This might not be important if one needs to just fetch the value.
If, after:
var myVal = appData.foo && appData.foo.bar && appData.foo.bar.setting;
myVal is not undefined, it will hold the value of appData.foo.bar.setting.
You can try this
var x = {y:{z:{a:'b'}}}
x && x.y && x.y.z && x.y.z.a //returns 'b'
This is not as good as the groovy expression but it works. The evaluation stops after encountering the first undefined variable.
var product = ...,
offering = (product||{}).offering,
merchant = (offering||{}).merchant,
merchantName = (merchant||{}).name;
if (merchantName)
displayMerchantName(merchantName);
http://osteele.com/archives/2007/12/cheap-monads
I just cooked this up so it might not work exactly right, I've also included two test cases.
function hasPropertyChain(o, properties) {
var i = 0,
currentPropertyChain = o;
if(!o) {
return false;
}
while(currentPropertyChain = currentPropertyChain[properties[i++]]);
return i - 1 === properties.length;
}
alert(hasPropertyChain({a:{b:{c:'a'}}}, ['a','b','c'])); // true
alert(hasPropertyChain({a:{b:{c:'a'}}}, ['a','b','c', 'd'])); // false

Check if an array item is set in JS

I've got an array
var assoc_pagine = new Array();
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
I tried
if (assoc_pagine[var] != "undefined") {
but it doesn't seem to work
I'm using jquery, I don't know if it can help
Thanks
Use the in keyword to test if a attribute is defined in a object
if (assoc_var in assoc_pagine)
OR
if ("home" in assoc_pagine)
There are quite a few issues here.
Firstly, is var supposed to a variable has the value "home", "work" or "about"? Or did you mean to inspect actual property called "var"?
If var is supposed to be a variable that has a string value, please note that var is a reserved word in JavaScript and you will need to use another name, such as assoc_var.
var assoc_var = "home";
assoc_pagine[assoc_var] // equals 0 in your example
If you meant to inspect the property called "var", then you simple need to put it inside of quotes.
assoc_pagine["var"]
Then, undefined is not the same as "undefined". You will need typeof to get the string representation of the objects type.
This is a breakdown of all the steps.
var assoc_var = "home";
var value = assoc_pagine[assoc_var]; // 0
var typeofValue = typeof value; // "number"
So to fix your problem
if (typeof assoc_pagine[assoc_var] != "undefined")
update: As other answers have indicated, using a array is not the best sollution for this problem. Consider using a Object instead.
var assoc_pagine = new Object();
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
var assoc_pagine = new Array();
assoc_pagine["home"]=0;
Don't use an Array for this. Arrays are for numerically-indexed lists. Just use a plain Object ({}).
What you are thinking of with the 'undefined' string is probably this:
if (typeof assoc_pagine[key]!=='undefined')
This is (more or less) the same as saying
if (assoc_pagine[key]!==undefined)
However, either way this is a bit ugly. You're dereferencing a key that may not exist (which would be an error in any more sensible language), and relying on JavaScript's weird hack of giving you the special undefined value for non-existent properties.
This also doesn't quite tell you if the property really wasn't there, or if it was there but explicitly set to the undefined value.
This is a more explicit, readable and IMO all-round better approach:
if (key in assoc_pagine)
var is a statement... so it's a reserved word... So just call it another way.
And that's a better way of doing it (=== is better than ==)
if(typeof array[name] !== 'undefined') {
alert("Has var");
} else {
alert("Doesn't have var");
}
This is not an Array.
Better declare it like this:
var assoc_pagine = {};
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
or
var assoc_pagine = {
home:0,
about:1,
work:2
};
To check if an object contains some label you simply do something like this:
if('work' in assoc_pagine){
// do your thing
};
This worked for me
if (assoc_pagine[var] != undefined) {
instead this
if (assoc_pagine[var] != "undefined") {
TLDR; The best I can come up with is this: (Depending on your use case, there are a number of ways to optimize this function.)
function arrayIndexExists(array, index){
if ( typeof index !== 'number' && index === parseInt(index).toString()) {
index = parseInt(index);
} else {
return false;//to avoid checking typeof again
}
return typeof index === 'number' && index % 1===0 && index >= 0 && array.hasOwnKey(index);
}
The other answer's examples get close and will work for some (probably most) purposes, but are technically quite incorrect for reasons I explain below.
Javascript arrays only use 'numerical' keys. When you set an "associative key" on an array, you are actually setting a property on that array object, not an element of that array. For example, this means that the "associative key" will not be iterated over when using Array.forEach() and will not be included when calculating Array.length. (The exception for this is strings like '0' will resolve to an element of the array, but strings like ' 0' won't.)
Additionally, checking array element or object property that doesn't exist does evaluate as undefined, but that doesn't actually tell you that the array element or object property hasn't been set yet. For example, undefined is also the result you get by calling a function that doesn't terminate with a return statement. This could lead to some strange errors and difficulty debugging code.
This can be confusing, but can be explored very easily using your browser's javascript console. (I used chrome, each comment indicates the evaluated value of the line before it.);
var foo = new Array();
foo;
//[]
foo.length;
//0
foo['bar'] = 'bar';
//"bar"
foo;
//[]
foo.length;
//0
foo.bar;
//"bar"
This shows that associative keys are not used to access elements in the array, but for properties of the object.
foo[0] = 0;
//0
foo;
//[0]
foo.length;
//1
foo[2] = undefined
//undefined
typeof foo[2]
//"undefined"
foo.length
//3
This shows that checking typeof doesn't allow you to see if an element has been set.
var foo = new Array();
//undefined
foo;
//[]
foo[0] = 0;
//0
foo['0']
//0
foo[' 0']
//undefined
This shows the exception I mentioned above and why you can't just use parseInt();
If you want to use associative arrays, you are better off using simple objects as other answers have recommended.
if (assoc_pagine.indexOf('home') > -1) {
// we have home element in the assoc_pagine array
}
Mozilla indexOf
function isset(key){
ret = false;
array_example.forEach(function(entry) {
if( entry == key ){
ret = true;
}
});
return ret;
}
alert( isset("key_search") );
The most effective way:
if (array.indexOf(element) > -1) {
alert('Bingooo')
}
W3Schools

Categories

Resources