I'm trying to create a nice util function to validate strings. Conditions are:
Cannot be typeof "undefined"
Cannot be null
Must be a string i.e. not a number, object, array, etc.
Must have at least one character in it. So a string with value of '' would be invalid.
I found some pointers on this that suggest using RegEx is the way to do it but the following is not working when I give it a numeric value.
Here's what I have so far:
const isValidString = (str1) => {
if(typeof str1 === "undefined" || str1 === null) return false;
const validRegEx = /^[^\\\/&]*$/;
if(str1.match(validRegEx)) {
return true;
} else {
return false;
}
}
As I said, if send const str1 = 3; to this function, I get an error that reads:
"TypeError: badString.match is not a function
What am I missing?
if (str1 != null) will coerce the str1 value, and will check both against null and undefined.
EDIT: ignore this part (Also, you don't need to use a regex to check if there's at least one character. You can use the string length. str1.length will evaluate to a falsey value if it's 0, otherwise it will evaluate to a truethy value.) You need a strict boolean value, so it should be str1.length > 0.
function isValidString(str1) {
return str1 != null && typeof str1 === "string" && str1.length > 0;
}
Why don't you add a typeof str1 === 'string' as shown below
if(typeof str1 === 'string' && str1.match(validRegEx)) {
return true;
} else {
return false;
}
That is because the match method is only available on strings, and you are attempting to call it on a number.
I would suggest re-writing the function to ensure that the argument is a string, rather than only checking for null or undefined values:
const isValidString = str1 => {
if (!str1 || typeof str1 !== 'string') return false
const validRegEx = /^[^\\\/&]*$/
if (str1.match(validRegEx)) {
return true
} else {
return false
}
}
Convert number to string perform evaluating it
const isValidString = (str1) => {
str1 = str1.toString();
if(typeof str1 === "undefined" || str1 === null) return false;
const validRegEx = /^[^\\\/&]*$/;
if(str1.match(validRegEx)) {
return true;
} else {
return false;
}
}
console.log(isValidString(3))
Replace the if with following:
if(typeof str1 === "undefined" || str1 === null || typeof str1 !== 'string') return false;
Use RegExp#test instead, because your regular expression will always be available. Also, String#match returns an array (or null) which is not well-suited for boolean expressions and may produce unwanted results.
const isValidString = (str1) => {
if (typeof str1 === "undefined" || str1 === null) return false;
const validRegEx = /^[^\\\/&]*$/;
if (validRegEx.test(str1)) {
return true;
} else {
return false;
}
}
console.log(isValidString(1));
console.log(isValidString('string'));
Note, your regexp is still wrong because it validates the number as true. You need to tweak it more.
Credit to djfdev on this one, all I've really done is simplify his answer to be more succinct.
const isValidString = str1 => {
return typeof str1 === 'string' && /^[^\\\/&]*$/.test(str1);
}
Related
My instructions were to iterate through a string and remove all instances of the letter "a". I thought that it would be easy to find examples, but I was unable to do so. Some would remove the letter without the iteration, but that is not what the instructions asked. If someone could please look at my code and assist me in my task I would greatly appreciate it! The "removeA" function will iterate through the string now, and only console logs the !== "a", but for the life of me I can't figure out how to save it to a new string. Thanks in advance.
removeA = function(stringWithA) {
if (stringWithA === null || typeof (stringWithA) !== "string" || stringWithA === "") { //Checking for is null AND is not array
return 'Please enter a valid string';
} else {
lowerWithA = stringWithA.toLowerCase();
for (var i = 0; i < lowerWithA.length; i++) {
if (lowerWithA.charAt(i) !== "a") {
console.log(lowerWithA.charAt(i));
}
}
}
}
You can store the letters into an Array.
var removeA = function(stringWithA) {
if (stringWithA === null || typeof(stringWithA) !== "string" || stringWithA === "") { //Checking for is null AND is not array
return 'Please enter a valid string';
} else {
var newString = [];
lowerWithA = stringWithA.toLowerCase();
for (var i = 0; i < lowerWithA.length; i++) {
if (lowerWithA.charAt(i) !== "a") {
newString.push(lowerWithA.charAt(i))
}
}
return newString.join('');
}
}
console.log(removeA("Eleazar"))
Or, just use a regex:
var removeA = function(stringWithA) {
if (stringWithA === null || typeof(stringWithA) !== "string" || stringWithA === "") { //Checking for is null AND is not array
return 'Please enter a valid string';
} else {
return stringWithA.replace(/a/gi, '')
}
}
console.log(removeA("EleaaaaazAreeeeaaaElAAAAAeaaaEleEvene"))
Why not build a new string with all the characters that are not a?
var newString = "";
for (var i = 0; i < lowerWithA.length; i++) {
var letter = lowerWithA.charAt(i);
if (letter !== "a") {
newString += letter;
}
}
console.log(newString);
If you wanted to expand this to be case-insensitive:
...
if (letter !== 'a' || letter !== 'A') { ... }
And simply don't call String.toLowerCase() on the original string.
I suppose there's already a function that you need, replace:
var stringWithA = 'A aaaa bbbcc!';
alert(stringWithA.replace(/[Aa]/g, ''));
I'm attempting to write a filter for use in a grid that will catch all null, undefined, blank string, or other similar values and display a dash "-". I've written the following so far, but it doesn't catch null values, and I'm wondering if it could be more succinct and possibly refactored to avoid three layers of nested if/else statements. Percentage values need to be checked that they're over 0 and under 1. Also, negative numbers and 0's should be returned as is. Thanks!
angular.module('AdverseEventsExplorer.main').filter('emptyCellFilter', function ($filter) {
return function (input, cellFilter, args1, args2) {
if (cellFilter == undefined) {
return (angular.isNumber(input) || angular.isDefined(input) && input.length > 0) ? input : '-';
} else {
if (cellFilter.match(/pctg|percent|pctgFilter|incidence/ig)) {
return (input > 0 && input < 1.0000000) ? $filter(cellFilter)(input, args1, args2) : '-';
} else {
return (angular.isNumber(input) || angular.isDefined(input) && input.length > 0) ? input : '-';
}
}
};
});
Version 2.0 taking into account #tymeJV's comment:
angular.module('AdverseEventsExplorer.main').filter('emptyCellFilter', function ($filter) {
return function (input, cellFilter, args1, args2) {
if (!cellFilter) {
return (angular.isNumber(input) || (input)) ? input : '-';
} else {
if (cellFilter.match(/pctg|percent|pctgFilter|incidence/ig)) {
return (input > 0 && input < 1.0000000) ? $filter(cellFilter)(input, args1, args2) : '-';
} else {
return (angular.isNumber(input) || (input)) ? $filter(cellFilter)(input, args1, args2) : '-';
}
}
};
});
Whenever you encounter a function that's getting too complex to refactor try extracting some of the smaller statements to concisely named variables. It makes it much easier for our brains to keep track of the function's requirements, and it's also more readable to new devs reading your code.
var inputHasValue = angular.isNumber(input) || input;
if(!inputHasValue){
return '-';
}
if (!cellFilter) {
return input;
}
var isPercentageCell = cellFilter.match(/pctg|percent|pctgFilter|incidence/ig);
var valueIsInRange = input > 0 && input < 1;
if(!isPercentageCell || valueIsInRange){
return $filter(cellFilter)(input, args1, args2);
}
return '-';
typeof x ==='number' || !!x
is false when x is null, undefined or empty string
Only one case in which it doesn't work – if you need to filter boolean variables, but your case doesn't seem to need it.
Anyway in that case you can use
typeof x === 'boolean' || typeof x ==='number' || !!x
if localStorage["BestScore"] = undefined;
{
localStorage["BestScore"]=0;
maxScore=0;
}
var maxScore=localStorage["BestScore"];
var newScore=false
function drawScore(score) {
if (newScore == true && score < maxScore) {
newScore = false;
}
if (score > maxScore) {
newScore = true;
localStorage["BestScore"] = score;
if ([5, 10, 15, 20].indexOf(score) !== -1) {
play(sndMedal);
} else {
play(sndGain);
}
}
This code is to set the max score and then store it but it doesn't seem to set the local storage to 0 if undefined.
if localStorage["BestScore"] = undefined;
should be:
if( typeof localStorage["BestScore"] === 'undefined' )
However if you need to check a variable against undefined value, there is no need to invent any special method, since JavaScript has a typeof operator, which is simple, fast and cross-platform:
if (typeof localStorage["BestScore"] === "undefined") {
localStorage["BestScore"] = 0;
}
It returns a string indicating the type of the variable or other unevaluated operand. The main advantage of this method, compared to if (value === undefined) { ... }, is that typeof will never raise an exception in case if variable value does not exist.
if localStorage["BestScore"] = undefined;
should be ==
else you are assigning, not comparing.
use == or === as a comparison operator, then it should be fine
I am using the following Javascript:
if (typeof content !== 'undefined' && content.length > 0) {
$state.transitionTo('admin.content', { content: content })
}
I thought this was safe to use but it gives me an error saying:
TypeError: Cannot read property 'length' of null
I am using the following function to decide if something is a number:
isNumber: function (num) {
// Return false if num is null or an empty string
if (num === null || (typeof num === "string" && num.length === 0)) {
return false;
}
var rtn = !isNaN(num)
return rtn;
},
How can I write a similar function that would very safely determine if
something is a string with a length of more than 0?
if (typeof num === "string" && num.length > 0)
{
alert("You've got yourself a string with more than 0 characters");
}
if (typeof(num) === "string" && num.length > 0) {...}
I would like to add upon the existing answers.
if string object is created through new constructor function then the following code will return false
var stringObj = new String("my string");
typeof stringObj === "string" // this will be false, because the type is object
a better way would be to test through the constructor property of the stringObj
stringObj.constructor === String
this condition will be true if the stringObj was created in the following two ways
var stringObj = "my string";
Or
var stringObj = new String("my string");
I was surprised to see that
/a/ === /a/
evaluates to false in JavaScript. Reading through the specs:
Two regular expression literals in a program evaluate to regular
expression objects that never compare as === to each other even if the
two literals' contents are identical.
Since === cannot be used to test for equality, how can equality of regular expressions be tested in JavaScript?
Here's a case that even covers ordering of flags.
function regexEqual(x, y) {
return (x instanceof RegExp) && (y instanceof RegExp) &&
(x.source === y.source) && (x.global === y.global) &&
(x.ignoreCase === y.ignoreCase) && (x.multiline === y.multiline);
}
Tests:
regexEqual(/a/, /a/) // true
regexEqual(/a/gi, /a/ig) // also true.
regeXEqual(/a/, /b/) // false
Here's a function that fully tests all the relevant regex properties and makes sure it's the right type of object:
function regexSame(r1, r2) {
if (r1 instanceof RegExp && r2 instanceof RegExp) {
var props = ["global", "multiline", "ignoreCase", "source", "dotAll", "sticky", "unicode"];
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (r1[prop] !== r2[prop]) {
return false;
}
}
return true;
}
return false;
}
And, since flags sometimes get added to the regex object with new features (as has happened since this original answer in 2012 - though the above code has been updated as of 2019), here's a version that is a bit more future proof on future flags being added since it compares whatever flags are there rather than looking for a specific set of flags. It sorts the flags before comparing to allow for minor differences in how the regex was specified that wouldn't not actually change functionality.
function regexSame(r1, r2) {
return r1 instanceof RegExp &&
r2 instanceof RegExp &&
r1.source === r2.source &&
r1.flags.split("").sort().join("") === r2.flags.split("").sort().join("");
}
Compare them using toString(), and check their type too:
var a = /a/,
b = /a/;
a.toString() === b.toString() && typeof(a) === typeof(b) //true
var c = /a/,
d = /b/;
c.toString() === d.toString() && typeof(c) === typeof(d) //false
You can check the types with typeof, then toString() both regexes and compare those. It won't cover cases with equivalent flags, such as /a/gi and /a/ig, though.
function regexEquals(a, b)
{
if (typeof a !== 'object' || typeof b !== 'object') return false;
return a.toString() === b.toString();
}
Unfortunately there's no more-specific type from typeof, so if you really want to make sure they're regexes (or regex-like) you could do something along these lines:
RegExp.prototype.regexEquals = function (other)
{
return (typeof other.regexEquals === 'function')
&& (this.toString() === other.toString());
}
Then:
/a/.regexEquals(/a/); // true
/a/.regexEquals(/b/); // false
Answers above didn't consider case-sensitivity. So built upon jfriend00's answer, the function should be
function regexEqual(a, b) {
if (!(a instanceof RegExp) || !(b instanceof RegExp)) {
return false;
}
let sourceA = a.source;
let sourceB = b.source;
const flagsA = a.flags.split('').sort().join(',');
const flagsB = b.flags.split('').sort().join(',');
if (flagsA.includes('i') && flagsB.includes('i')) {
sourceA = sourceA.toLowerCase();
sourceB = sourceB.toLowerCase();
}
return sourceA === sourceB && flagsA === flagsB;
}