I have 3 variables which are dynamic and might be null or undefined.
Example:
var str1= " hello";
var str2= " world";
var str= " how are you?";
and now I'm concatenating these string together to form a query in my searchlist:
query = str1&& str1 + str2&& str2 + str3&& str3; //o/p: "hello world how are you?
this results fine, however in any case when one of the str value is null or empty, I get this whe I concatenate these string:
query = str1&& str1 + str2&& str2 + str3&& str3; // o/p: "hello world undefined"
How can I avoid this undefined coming in my string?
You can use the logical or operator to provide a default value in case any string is null or undefined.
query = (str1 || '') + (str2 || '') + (str3 || '')
You can use the nullish coalescing operator to only provide default values for null and undefined and not for other falsey values. Remember to check the browser support.
query = (str1 ?? '') + (str2 ?? '') + (str3 ?? '')
I have a template in a String and I want to replace a few of the placeholders with the values that I have in another string. For every placeholder that I replace, I also want to insert a break tag.
For eg if #ADDRESS2# is found in the template, I am using the following code to replace all its occurrences with value in string val.address2.
template_html = template_html.replace(/#ADDRESS2#/g, '<br />'+ val.address_2);
However there are scenarios when the string val.address2 is empty. In that case, I do not want to insert the break tag.
So I changed my code as follows
if( val.address_2.length > 0 ) {
template_html = template_html.replace(/#ADDRESS2#/g, '<br />'+ val.address_2);
} else {
template_html = template_html.replace(/#ADDRESS2#/g, '');
}
Is there a better way to write the above code as I have multiple Placeholders and for each Placeholder I have to write the code 2 times.
Use a regex replacement, to which you pass a function.
That function will get the replacement keys as input, and depending on if there's a replacement available, it will insert a empty string, or the replacement with a linebreak:
const template = "#foo# this bla bla #bar# but #baz# and stuff";
const replacements = {
foo: "test",
bar: "",
baz: "not empty"
};
const result = template.replace(/#([^#]+)#/g, (match, key) => {
// If there's a replacement for the key, return that replacement with a `<br />`. Otherwise, return a empty string.
return replacements[key] !== undefined
? "<br />" + replacements[key]
: "";
});
console.log("template:", template);
console.log("result:", result);
The only "gotcha" here is that the keys in the template string have to match the keys in your replacements object. That's not necessarily a bad thing, though, as it would make it slightly more intuitive if you'd look back at your code later on.
The regex may look intimidating, but it's really quite simple:
/#([^#]+)#/g
/: The start of the regex,
#: Literally the # character,
(: The start of a capturing group,
[^#]+ Any character that isn't a #. The + makes sure it matches as many as possible,
): The end of a capturing group,
#: Literally the # character,
/g: The end of the regex. g is the global flag, so it doesn't stop at the first result.
The capturing group basically tells the regex to group everything that's between the brackets. The groups are then returned individually.
Perhaps you meant this?
var val = {
"address_1": "Address 1",
"address_2": "",
"address_10": "Address 10",
}
var template_html = `My address is #ADDRESS1# delivery address is #ADDRESS2# and billing is #ADDRESS10#`
template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(addr, num) {
var str = val["address_"+num]; return str?str+"<br/>":""
})
console.log(template_html)
If the same logic should be applied for multiple address fields, then you might benefit from a helper function:
template_html = template_html
.replace(/#CITY1#/g, PrefixBrIfNotEmpty(val.city_1))
.replace(/#CITY2#/g, PrefixBrIfNotEmpty(val.city_2))
.replace(/#CITY3#/g, PrefixBrIfNotEmpty(val.city_3))
.replace(/#ADDRESS1#/g, PrefixBrIfNotEmpty(val.address_1))
.replace(/#ADDRESS2#/g, PrefixBrIfNotEmpty(val.address_2))
.replace(/#ADDRESS3#/g, PrefixBrIfNotEmpty(val.address_3));
function PrefixBrIfNotEmpty(str) {
return str ? '<br />' + str : '';
}
You can use ternary operator (empty string evaluates to false)
template_html = template_html.replace(/#ADDRESS2#/g, val.address_2 ? '<br />'+ val.address_2 : '');
The simplest change is to use the ternary operator like this:
template_html = template_html.replace(/#ADDRESS2#/g, ( val.address_2.length > 0 ) ? '<br />'+ val.address_2 : '');
Still not particularly elegant but a bit shorter than the original.
You could take the value with a check.
template_html = template_html.replace(
/#ADDRESS2#/g,
val.address_2 && '<br />' + val.address_2
);
For more than one placeholder, you could take a dynamic approach and use same pattern for the search and replacements.
var val = { address_2: 'foo', country_1: 'bar' }
template_html = 'Address: #ADDRESS2#\nCountry: #COUNTRY1#\nnothing: #NOTHING#'
template_html = template_html.replace(
/#([^#]+)#/g,
(_, group) => {
var key = group.match(/^(\D+)(\d*)$/).slice(1).map(s => s.toLowerCase()).join('_');
return (val[key] || '') && '<br />' + val[key];
}
);
console.log(template_html);
For getting a smarter replacement, yoou could take the idea of same strings as tempate and for getting the data from an object. In this case, take the replacement value and take this as key for the object or take an empty string for unknown values.
var val = { ADDRESS2: 'foo', COUNTRY1: 'bar' }
template_html = 'Address: #ADDRESS2#\nCountry: #COUNTRY1#\nnothing: #NOTHING#'
template_html = template_html.replace(
/#([^#]+)#/g,
(_, key) => (val[key] || '') && '<br />' + val[key]
);
console.log(template_html);
You mean, something like this:
template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(address, number) {
return val.hasOwnProperty('address_' + number)
? '<br />' + val['address_' + number]
: '';
};
You should use the val.hasOwnProperty just in case that val.['address_' + number] contains a value like 0, false, '', undefined, NaN or other falsy values.
It makes sure the value is displayed anyway, because an undefined isn't the same as not having the property at all.
It also avoids to get a value from the prototype, just in case.
This is based on mplungjan's answer.
If this is undesirable, and you only want to show strings, try this:
template_html = template_html.replace(/#ADDRESS(\d+)#/g, function(address, number) {
return val.hasOwnProperty('address_' + number)
&& val['address_' + number].length
&& (
(typeof val['address_' + number]) === 'string'
|| val['address_' + number] instanceof String
)
? '<br />' + val['address_' + number]
: '';
};
All of this checking ensures that it is a non-empty string (or String instance, because new String() returns a string object).
Checking if it is an instance of String prevents issues due to typeof new String() returning object.
Arrays and array-like objects have a length attributes (e.g.: jQuery instance, NodeList, {length: 1}, [0] and similars), but you dont want to show them as strings.
Well, I'm working in a Chat Room Website... and I have this Problem... For a reason the Ternary Operator doesn't give me the right output...
That's the Code Piece of code that does the Job...
html = html.replace(/(#[a-zA-Z0-9]{1,})/, "<span class='" + (myUsername == "$1".replace('#', '') ? "highlighted-username" : "") + "'>$1</span>");
Let's say That my name is "jimisdam" and someone writes in the Chat "#jimisdam"... So... I'm getting the $1 and removing the '#' to compare it with the myUsername(which is "jimisdam")
WHAT'S WRONG ??
JS doesn't know that you want it to substitute $1 into place before doing the replacement. It sees a method call to html.replace which takes 2 arguments:
the regex to match
the string to replace with
To calculate the second parameter, it evaluates this expression:
"<span class='" + (myUsername == "$1".replace('#', '') ? "highlighted-username" : "") + "'>$1</span>"
Note that $1 doesn't mean anything special here, because we're still deciding what string to pass into the replacement function. So:
"$1".replace('#', '') just results in "$1"
so unless your username happens to be $1, the comparison will always be false
so an empty string will be added to the class attribute
so the argument passed will always be "<span class=''>$1</span>"
Only now does replace get to see the remaining instance of $1 and substitute in the captured value.
One way to achieve what you're trying to do is to pass in a function rather than a string as the second parameter. That way, you get the matched sections of string as variables, and can use them to calculate the replacement.
Untested example, because I'm on a phone:
html = html.replace(/(#[a-zA-Z0-9]{1,})/, function(match) { return "<span class='" + (myUsername == match.replace('#', '') ? "highlighted-username" : "") + "'>" + match + "</span>"; })
Your “$1” string literal does not hold a submatch. That’s wrong.
However, the replace() method also takes a function as second argument. Try this:
html = html.replace(/(#[a-zA-Z0-9]{1,})/,function(){
return '<span class="' +
(myUsername == arguments[0].replace('#','') ? 'highlighted-username' : '')
+ '">' + arguments[0] + '</span>';
});
I'm not sure what is happening in this line of javascript:
alert( (''+[][[]])[!+[]+!+[]] ); // shows "d"
What I've figured out:
var a = ! + []; // == true
var b = ! + [] + ! + []; // == 2
It seems that the second part is a reference into an array of letters or some sort, but I don't understand how that is coming from
(''+[][[]])
Also:
alert( (''+[][])[2] ); // nothing happens; console says "unexpected token ]"
alert( (''+[[]][])[2] ); // nothing happens; console says "unexpected token ]"
alert( (''+[[]][[]])[2] ); // shows "d"
alert( (""+true)[2] ); // shows "u"
I'll decompose it for you:
('' + [][[]])[!+[]+!+[]]
= ('' + undefined)[!+[]+!+[]] // [][[]] grabs the []th index of an empty array.
= 'undefined'[! + [] + ! + []]
= 'undefined'[(! + []) + (! + [])]
= 'undefined'[true + true]
= 'undefined'[2]
= 'd'
! + [] == true is explained here What's the significant use of unary plus and minus operators?
Because "" + true is the string "true", and the third character (index 2) is u.
Things like ! + [] work because + can also be a unary operator, see this SO question.
alert( (""+true)[2] ); // shows "u"
It's returning the 3rd letter of the string "true".
What does this return?
alert( (''+[[]][[]]));
string1 = prompt("String 1?");
string2 = prompt("String 2?");
if (string1.length == string2.length)
alert (string1 + " and " + string2 + " : are identical in size.")
else
alert (string1 + " and " + string2 + " : not identical in size.")
for(i=0; i<string1.length; i++)
{
for(j=0; j<string2.length; j++)
{
if (string1.charAt[i] == string2.charAt[i])
alert (string1.charAt[i] + " and " + string2.charAt[j] + " : are identical values.")
else
alert (string1.charAt[i] + " and " + string2.charAt[j] + " : are non-identical values.")
}
};
The second part of the code keeps returning "undefined" and "undefined". I'm trying to compare both strings to see if they hold identical values. Would appreciate any help!
You are using the wrong index when you compare the characters. This:
if (string1.charAt[i] == string2.charAt[i])
should be:
if (string1.charAt(i) == string2.charAt(j))
Besides using parantheses, as Rob W pointed out, you should use the variable j to access the character in string2.
I'm not sure why you are comparing each character in one string with every character in the other string, though... If you actually want to compare each character to the corresponding character in the other string, then you should not have nested loops but a single loop.
Use charAt(i) instead of charAt[i] (parentheses instead of square braces).charAt is a String method, not a string's property.
Equivalent methods:
string1[i]
string1.charAt(i)
string1.substr(i, 1)
string.substring(i, i+1)
Wtf?
string1 === string2
Why not?