String conversion to undefined/null/number/boolean - javascript

Do you know any better and faster way to convert a string to the type it represents?
I've always been using this function:
var convertType = function (value){
if (value === "undefined") return undefined;
if (value === "null") return null;
if (value === "true") return true;
if (value === "false") return false;
var v = Number (value);
return isNaN (v) ? value : v;
};
Candidates:
//Me, Gabriel Llamas
var cast1 = function (value){
if (value === "undefined") return undefined;
if (value === "null") return null;
if (value === "true") return true;
if (value === "false") return false;
var v = Number (value);
return isNaN (v) ? value : v;
};
//KooiInc
var cast2 = function (value){
var v = Number (value);
return !isNaN(v) ? v :
value === "undefined" ? undefined
: value === "null" ? null
: value === "true" ? true
: value === "false" ? false
: value
};
//LightStyle
var cast3 = function (value){
try {
return (new Function("return " + value + ";"))();
} catch(e) {
return value;
}
};
//Emmissary's proposal
var cast4 = function (value){
if (value === "undefined") return undefined;
try{
return JSON.parse (value);
}catch (e){
return value;
}
};
Benchmark code (using speedy):
var fn = function (cast){
cast ("undefined");
cast ("null");
cast ("true");
cast ("false");
cast ("12");
cast ("12.34");
cast ("asd");
};
speedy.run ({
"cast 1": function (){
fn (cast1);
},
"cast 2": function (){
fn (cast2);
},
"cast 3": function (){
fn (cast3);
},
"cast 4": function (){
fn (cast4);
}
});
Result:
File: string-conversion.js
Node v0.10.18
V8 v3.14.5.9
Speedy v0.0.8
Benchmarks: 4
Timeout: 1000ms (1s 0ms)
Samples: 3
Total time per benchmark: ~3000ms (3s 0ms)
Total time: ~12000ms (12s 0ms)
Higher is better (ops/sec)
cast 1
6,270,458 ± 0.2%
cast 2
3,305,103 ± 0.0%
cast 3
54,952 ± 0.0%
cast 4
82,790 ± 0.4%
Elapsed time: 12109ms (12s 109ms)

This is a simple function which involves the use of a function to evaluate the strings. This way you can remove the part of cases' "switch". Be aware that this handles also assignments to global variables, so I recommend it only if you know anytime where is the source from(don't allow users to use this function!)
var convertType = function (value){
try {
return (new Function("return " + value + ";"))();
} catch(e) {
return value;
}
};
You can see the jsfiddle here.

How about:
var convertType = function (value){
var values = {undefined: undefined, null: null, true: true, false: false}
,isNumber = !isNaN(+(value));
return isNumber && +(value) || !(value in values) && value || values[value];
};
convertType('null'); //=> null
convertType('something'); //=> "something"
convertType('57.321'); //=> 57.321
convertType('undefined'); //=> undefined
This seems faster # jsPerf
var convertType = function (value){
var v = Number (value);
return !isNaN(v) ? v :
value === "undefined" ? undefined
: value === "null" ? null
: value === "true" ? true
: value === "false" ? false
: value
}

var string2literal = function (value){
var maps = {
"NaN": NaN,
"null": null,
"undefined": undefined,
"Infinity": Infinity,
"-Infinity": -Infinity
}
return ((value in maps) ? maps[value] : value);
};
There are many weird rules in dynamic data type converting, just map it.

Related

Boolean conditionals with placeholder [duplicate]

Is there a string.Empty in JavaScript, or is it just a case of checking for ""?
Empty string, undefined, null, ...
To check for a truthy value:
if (strValue) {
// strValue was non-empty string, true, 42, Infinity, [], ...
}
To check for a falsy value:
if (!strValue) {
// strValue was empty string, false, 0, null, undefined, ...
}
Empty string (only!)
To check for exactly an empty string, compare for strict equality against "" using the === operator:
if (strValue === "") {
// strValue was empty string
}
To check for not an empty string strictly, use the !== operator:
if (strValue !== "") {
// strValue was not an empty string
}
For checking if a variable is falsey or if it has length attribute equal to zero (which for a string, means it is empty), I use:
function isEmpty(str) {
return (!str || str.length === 0 );
}
(Note that strings aren't the only variables with a length attribute, arrays have them as well, for example.)
Alternativaly, you can use the (not so) newly optional chaining and arrow functions to simplify:
const isEmpty = (str) => (!str?.length);
It will check the length, returning undefined in case of a nullish value, without throwing an error. In the case of an empty value, zero is falsy and the result is still valid.
For checking if a variable is falsey or if the string only contains whitespace or is empty, I use:
function isBlank(str) {
return (!str || /^\s*$/.test(str));
}
If you want, you can monkey-patch the String prototype like this:
String.prototype.isEmpty = function() {
// This doesn't work the same way as the isEmpty function used
// in the first example, it will return true for strings containing only whitespace
return (this.length === 0 || !this.trim());
};
console.log("example".isEmpty());
Note that monkey-patching built-in types are controversial, as it can break code that depends on the existing structure of built-in types, for whatever reason.
All the previous answers are good, but this will be even better. Use dual NOT operators (!!):
if (!!str) {
// Some code here
}
Or use type casting:
if (Boolean(str)) {
// Code here
}
Both do the same function. Typecast the variable to Boolean, where str is a variable.
It returns false for null, undefined, 0, 000, "", false.
It returns true for all string values other than the empty string (including strings like "0" and " ")
The closest thing you can get to str.Empty (with the precondition that str is a String) is:
if (!str.length) { ...
If you need to make sure that the string is not just a bunch of empty spaces (I'm assuming this is for form validation) you need to do a replace on the spaces.
if(str.replace(/\s/g,"") == ""){
}
I use:
function empty(e) {
switch (e) {
case "":
case 0:
case "0":
case null:
case false:
case undefined:
return true;
default:
return false;
}
}
empty(null) // true
empty(0) // true
empty(7) // false
empty("") // true
empty((function() {
return ""
})) // false
Performance
I perform tests on macOS v10.13.6 (High Sierra) for 18 chosen solutions. Solutions works slightly different (for corner-case input data) which was presented in the snippet below.
Conclusions
the simple solutions based on !str,==,=== and length are fast for all browsers (A,B,C,G,I,J)
the solutions based on the regular expression (test,replace) and charAt are slowest for all browsers (H,L,M,P)
the solutions marked as fastest was fastest only for one test run - but in many runs it changes inside 'fast' solutions group
Details
In the below snippet I compare results of chosen 18 methods by use different input parameters
"" "a" " "- empty string, string with letter and string with space
[] {} f- array, object and function
0 1 NaN Infinity - numbers
true false - Boolean
null undefined
Not all tested methods support all input cases.
function A(str) {
let r=1;
if (!str)
r=0;
return r;
}
function B(str) {
let r=1;
if (str == "")
r=0;
return r;
}
function C(str) {
let r=1;
if (str === "")
r=0;
return r;
}
function D(str) {
let r=1;
if(!str || 0 === str.length)
r=0;
return r;
}
function E(str) {
let r=1;
if(!str || /^\s*$/.test(str))
r=0;
return r;
}
function F(str) {
let r=1;
if(!Boolean(str))
r=0;
return r;
}
function G(str) {
let r=1;
if(! ((typeof str != 'undefined') && str) )
r=0;
return r;
}
function H(str) {
let r=1;
if(!/\S/.test(str))
r=0;
return r;
}
function I(str) {
let r=1;
if (!str.length)
r=0;
return r;
}
function J(str) {
let r=1;
if(str.length <= 0)
r=0;
return r;
}
function K(str) {
let r=1;
if(str.length === 0 || !str.trim())
r=0;
return r;
}
function L(str) {
let r=1;
if ( str.replace(/\s/g,"") == "")
r=0;
return r;
}
function M(str) {
let r=1;
if((/^\s*$/).test(str))
r=0;
return r;
}
function N(str) {
let r=1;
if(!str || !str.trim().length)
r=0;
return r;
}
function O(str) {
let r=1;
if(!str || !str.trim())
r=0;
return r;
}
function P(str) {
let r=1;
if(!str.charAt(0))
r=0;
return r;
}
function Q(str) {
let r=1;
if(!str || (str.trim()==''))
r=0;
return r;
}
function R(str) {
let r=1;
if (typeof str == 'undefined' ||
!str ||
str.length === 0 ||
str === "" ||
!/[^\s]/.test(str) ||
/^\s*$/.test(str) ||
str.replace(/\s/g,"") === "")
r=0;
return r;
}
// --- TEST ---
console.log( ' "" "a" " " [] {} 0 1 NaN Infinity f true false null undefined ');
let log1 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")} ${f([])} ${f({})} ${f(0)} ${f(1)} ${f(NaN)} ${f(Infinity)} ${f(f)} ${f(true)} ${f(false)} ${f(null)} ${f(undefined)}`);
let log2 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")} ${f([])} ${f({})} ${f(0)} ${f(1)} ${f(NaN)} ${f(Infinity)} ${f(f)} ${f(true)} ${f(false)}`);
let log3 = (s,f)=> console.log(`${s}: ${f("")} ${f("a")} ${f(" ")}`);
log1('A', A);
log1('B', B);
log1('C', C);
log1('D', D);
log1('E', E);
log1('F', F);
log1('G', G);
log1('H', H);
log2('I', I);
log2('J', J);
log3('K', K);
log3('L', L);
log3('M', M);
log3('N', N);
log3('O', O);
log3('P', P);
log3('Q', Q);
log3('R', R);
And then for all methods I perform speed test case str = "" for browsers Chrome v78.0.0, Safari v13.0.4, and Firefox v71.0.0 - you can run tests on your machine here
You can use lodash:
_.isEmpty(value).
It covers a lot of cases like {}, '', null, undefined, etc.
But it always returns true for Number type of JavaScript primitive data types like _.isEmpty(10) or _.isEmpty(Number.MAX_VALUE) both returns true.
Very generic "All-In-One" Function (not recommended though):
function is_empty(x)
{
return ( //don't put newline after return
(typeof x == 'undefined')
||
(x == null)
||
(x == false) //same as: !x
||
(x.length == 0)
||
(x == 0) // note this line, you might not need this.
||
(x == "")
||
(x.replace(/\s/g,"") == "")
||
(!/[^\s]/.test(x))
||
(/^\s*$/.test(x))
);
}
However, I don't recommend to use that, because your target variable should be of specific type (i.e. string, or numeric, or object?), so apply the checks that are relative to that variable.
var s; // undefined
var s = ""; // ""
s.length // 0
There's nothing representing an empty string in JavaScript. Do a check against either length (if you know that the var will always be a string) or against ""
Try:
if (str && str.trim().length) {
//...
}
I would not worry too much about the most efficient method. Use what is most clear to your intention. For me that's usually strVar == "".
As per the comment from Constantin, if strVar could some how end up containing an integer 0 value, then that would indeed be one of those intention-clarifying situations.
A lot of answers, and a lot of different possibilities!
Without a doubt for quick and simple implementation the winner is: if (!str.length) {...}
However, as many other examples are available. The best functional method to go about this, I would suggest:
function empty(str)
{
if (typeof str == 'undefined' || !str || str.length === 0 || str === "" || !/[^\s]/.test(str) || /^\s*$/.test(str) || str.replace(/\s/g,"") === "")
return true;
else
return false;
}
A bit excessive, I know.
check that var a; exist
trim out the false spaces in the value, then test for emptiness
if ((a)&&(a.trim()!=''))
{
// if variable a is not empty do this
}
You could also go with regular expressions:
if((/^\s*$/).test(str)) { }
Checks for strings that are either empty or filled with whitespace.
I usually use something like this,
if (!str.length) {
// Do something
}
Also, in case you consider a whitespace filled string as "empty".
You can test it with this regular expression:
!/\S/.test(string); // Returns true if blank.
If one needs to detect not only empty but also blank strings, I'll add to Goral's answer:
function isEmpty(s){
return !s.length;
}
function isBlank(s){
return isEmpty(s.trim());
}
if ((str?.trim()?.length || 0) > 0) {
// str must not be any of:
// undefined
// null
// ""
// " " or just whitespace
}
Or in function form:
const isNotNilOrWhitespace = input => (input?.trim()?.length || 0) > 0;
const isNilOrWhitespace = input => (input?.trim()?.length || 0) === 0;
Starting with:
return (!value || value == undefined || value == "" || value.length == 0);
Looking at the last condition, if value == "", its length must be 0. Therefore drop it:
return (!value || value == undefined || value == "");
But wait! In JavaScript, an empty string is false. Therefore, drop value == "":
return (!value || value == undefined);
And !undefined is true, so that check isn't needed. So we have:
return (!value);
And we don't need parentheses:
return !value
I use a combination, and the fastest checks are first.
function isBlank(pString) {
if (!pString) {
return true;
}
// Checks for a non-white space character
// which I think [citation needed] is faster
// than removing all the whitespace and checking
// against an empty string
return !/[^\s]+/.test(pString);
}
I have not noticed an answer that takes into account the possibility of null characters in a string. For example, if we have a null character string:
var y = "\0"; // an empty string, but has a null character
(y === "") // false, testing against an empty string does not work
(y.length === 0) // false
(y) // true, this is also not expected
(y.match(/^[\s]*$/)) // false, again not wanted
To test its nullness one could do something like this:
String.prototype.isNull = function(){
return Boolean(this.match(/^[\0]*$/));
}
...
"\0".isNull() // true
It works on a null string, and on an empty string and it is accessible for all strings. In addition, it could be expanded to contain other JavaScript empty or whitespace characters (i.e. nonbreaking space, byte order mark, line/paragraph separator, etc.).
Meanwhile we can have one function that checks for all 'empties' like null, undefined, '', ' ', {}, [].
So I just wrote this.
var isEmpty = function(data) {
if(typeof(data) === 'object'){
if(JSON.stringify(data) === '{}' || JSON.stringify(data) === '[]'){
return true;
}else if(!data){
return true;
}
return false;
}else if(typeof(data) === 'string'){
if(!data.trim()){
return true;
}
return false;
}else if(typeof(data) === 'undefined'){
return true;
}else{
return false;
}
}
Use cases and results.
console.log(isEmpty()); // true
console.log(isEmpty(null)); // true
console.log(isEmpty('')); // true
console.log(isEmpty(' ')); // true
console.log(isEmpty(undefined)); // true
console.log(isEmpty({})); // true
console.log(isEmpty([])); // true
console.log(isEmpty(0)); // false
console.log(isEmpty('Hey')); // false
I did some research on what happens if you pass a non-string and non-empty/null value to a tester function. As many know, (0 == "") is true in JavaScript, but since 0 is a value and not empty or null, you may want to test for it.
The following two functions return true only for undefined, null, empty/whitespace values and false for everything else, such as numbers, Boolean, objects, expressions, etc.
function IsNullOrEmpty(value)
{
return (value == null || value === "");
}
function IsNullOrWhiteSpace(value)
{
return (value == null || !/\S/.test(value));
}
More complicated examples exists, but these are simple and give consistent results. There is no need to test for undefined, since it's included in (value == null) check. You may also mimic C# behaviour by adding them to String like this:
String.IsNullOrEmpty = function (value) { ... }
You do not want to put it in Strings prototype, because if the instance of the String-class is null, it will error:
String.prototype.IsNullOrEmpty = function (value) { ... }
var myvar = null;
if (1 == 2) { myvar = "OK"; } // Could be set
myvar.IsNullOrEmpty(); // Throws error
I tested with the following value array. You can loop it through to test your functions if in doubt.
// Helper items
var MyClass = function (b) { this.a = "Hello World!"; this.b = b; };
MyClass.prototype.hello = function () { if (this.b == null) { alert(this.a); } else { alert(this.b); } };
var z;
var arr = [
// 0: Explanation for printing, 1: actual value
['undefined', undefined],
['(var) z', z],
['null', null],
['empty', ''],
['space', ' '],
['tab', '\t'],
['newline', '\n'],
['carriage return', '\r'],
['"\\r\\n"', '\r\n'],
['"\\n\\r"', '\n\r'],
['" \\t \\n "', ' \t \n '],
['" txt \\t test \\n"', ' txt \t test \n'],
['"txt"', "txt"],
['"undefined"', 'undefined'],
['"null"', 'null'],
['"0"', '0'],
['"1"', '1'],
['"1.5"', '1.5'],
['"1,5"', '1,5'], // Valid number in some locales, not in JavaScript
['comma', ','],
['dot', '.'],
['".5"', '.5'],
['0', 0],
['0.0', 0.0],
['1', 1],
['1.5', 1.5],
['NaN', NaN],
['/\S/', /\S/],
['true', true],
['false', false],
['function, returns true', function () { return true; } ],
['function, returns false', function () { return false; } ],
['function, returns null', function () { return null; } ],
['function, returns string', function () { return "test"; } ],
['function, returns undefined', function () { } ],
['MyClass', MyClass],
['new MyClass', new MyClass()],
['empty object', {}],
['non-empty object', { a: "a", match: "bogus", test: "bogus"}],
['object with toString: string', { a: "a", match: "bogus", test: "bogus", toString: function () { return "test"; } }],
['object with toString: null', { a: "a", match: "bogus", test: "bogus", toString: function () { return null; } }]
];
I didn't see a good answer here (at least not an answer that fits for me)
So I decided to answer myself:
value === undefined || value === null || value === "";
You need to start checking if it's undefined. Otherwise your method can explode, and then you can check if it equals null or is equal to an empty string.
You cannot have !! or only if(value) since if you check 0 it's going to give you a false answer (0 is false).
With that said, wrap it up in a method like:
public static isEmpty(value: any): boolean {
return value === undefined || value === null || value === "";
}
PS.: You don't need to check typeof, since it would explode and throw even before it enters the method
Trimming whitespace with the null-coalescing operator:
if (!str?.trim()) {
// do something...
}
There is a lot of useful information here, but in my opinion, one of the most important elements was not addressed.
null, undefined, and "" are all falsy.
When evaluating for an empty string, it's often because you need to replace it with something else.
In which case, you can expect the following behavior.
var a = ""
var b = null
var c = undefined
console.log(a || "falsy string provided") // prints ->"falsy string provided"
console.log(b || "falsy string provided") // prints ->"falsy string provided"
console.log(c || "falsy string provided") // prints ->"falsy string provided"
With that in mind, a method or function that can return whether or not a string is "", null, or undefined (an invalid string) versus a valid string is as simple as this:
const validStr = (str) => str ? true : false
validStr(undefined) // returns false
validStr(null) // returns false
validStr("") // returns false
validStr("My String") // returns true
Try this:
export const isEmpty = string => (!string || !string.length);
All these answers are nice.
But I cannot be sure that variable is a string, doesn't contain only spaces (this is important for me), and can contain '0' (string).
My version:
function empty(str){
return !str || !/[^\s]+/.test(str);
}
empty(null); // true
empty(0); // true
empty(7); // false
empty(""); // true
empty("0"); // false
empty(" "); // true
Sample on jsfiddle.
There's no isEmpty() method, you have to check for the type and the length:
if (typeof test === 'string' && test.length === 0){
...
The type check is needed in order to avoid runtime errors when test is undefined or null.

JavaScriptClass : Simple conditional (ternary) Operator returns wrong result

I have the following code, using a ternary operator to terun if a value is true or false.
My expected result of would be pp is true, however i get the result that it is false.
How can this be? This doesnt make sense for me.
const test = (x) => {
(x === 1) ? true : false;
}
let pp = test(1); // SHOULD BE TRUE
if (pp) {console.log('pp is true')}
else {console.log('pp is false')}; // PRINTS FALSE, BUT SHOULD BE TRUE
You need to return the boolean:
const test = (x) => {
return (x === 1) ? true : false;
}
let pp = test(1);
if (pp) {console.log('pp is true')}
else {console.log('pp is false')};
with the brackets { } you need to add "return" in the body
const test = (x) => {
return (x === 1) ? true : false;
}
or without brackets
const test = (x) => (x === 1) ? true : false;

How to check two conditions with && correctly

I want to loop through an array and check if each element is a number OR a string that could potentially turned into a number (e.g. "42"). If it can be "converted" then the element should be stored in a new array.
This is my code where I push all converted elements into a new array. Notice: I also want to count how many elements were "converted" from a string into a number and how many were not.
function numberConverter(arr) {
var converted = []
var counterConverted = 0
var counterNotConverted = 0
for (var c of arr) {
if (typeof c == "string" && Number(c) == "number") {
counterConverted++;
parseInt(c, 10);
converted.push(c)
} else {
counterNotConverted++
}
}
if (counterConverted == 0) {
return "no need for conversion"
} else {
return counterConverted + " were converted to numbers: " + converted + "; " + counterNotConverted + " couldn't be converted"
}
}
I know that my if condition
if(typeof c == "string" && Number(c) == "number")
is flawed logically, but I can't make up why.
Thanks for any hints and please explain it in beginner terms.
You can test if a string could be converted to a number like so:
val !== "" && Number.isNaN(Number(val)) === false
And the code could be written like so:
function numberConverter(arr) {
var converted = [];
var notconverted = [];
arr.forEach(function(val) {
if (typeof val === "number") {
converted.push(val);
} else if (typeof val === "string" && val !== "" && Number.isNaN(Number(val)) === false) {
converted.push(Number(val));
} else {
notconverted.push(val);
}
});
console.log("converted", converted);
console.log("not converted", notconverted);
}
numberConverter([0, "1", "", "123-foo", undefined, null, true, [], {}]);
The best solution is to use a functional approach to the code rather than an imperative one.
let arrayNumbers = ["Vadim", 99, {}, [], "100", "55AA", "AA55", Infinity, "false", true, null, -65.535, 2E1, "2E2"].filter( value => value !== null && value != Infinity && value !== '' && !isNaN(Number(value)) && !['boolean','array','object'].includes(typeof value)).map(value => +value);
console.log('Was Converted to Numbers:', arrayNumbers);
You need to check typeof string and isNaN in ESLint way (Number.isNaN(Number())).
function numberConverter(arr) {
const converted = [];
let counterConverted = 0;
for (let i = 0; i < arr.length; i += 1) {
const str = arr[i];
if (str && typeof str === 'string' && !Number.isNaN(Number(str))) {
const number = parseInt(str, 10);
converted.push(number);
counterConverted += 1;
}
}
const counterNotConverted = arr.length - converted.length;
if (counterConverted === 0) {
return 'No need for conversion.';
}
return `${counterConverted} were converted to numbers: ${converted.join(',')}; ${counterNotConverted} couldn't be converted`;
}
console.log(`'${numberConverter(['id', null, {}])}'`); // No need for conversion.
console.log(`'${numberConverter(['1', '-1', 'val'])}'`); // 2 were converted to numbers: [1,-1]; 1 couldn't be converted
console.log(`'${numberConverter(['1', '-1', '0', '1.5', 'val'])}'`); // 4 were converted to numbers: [1,-1,0,1]; 1 couldn't be converted

Javascript enters if statement when the condition should evaluate false

I have a problem where javascript enters the if statement when the condition should evaluate false. I have the javascript linked to a HTML. The HTML uses form as its input for each variable, when nothing is entered into any of the form input type, the javascript outputs "0".
When 5 is entered into initialVelocity, and 45 is entered into finalVelocity the output is 50.
Feel free to make fun of my coding style, all answers are appreciated!
function physicsFunction() {
var initialVelocity = document.getElementById('formInitialV').elements['initialVName'].value;
var finalVelocity = document.getElementById('formFinalV').elements['finalVName'].value;
var time = document.getElementById('formTime').elements['timeName'].value;
var acceleration = document.getElementById('formAcceleration').elements['accelerationName'].value;
var averageAcceleration = document.getElementById('formAvgAcceleration').elements['avgAccelerationName'].value;
var displacement = document.getElementById('formDisplacement').elements['displacementName'].value;
var averageVelocity = document.getElementById('formAvgVelocity').elements['avgVelocityName'].value;
if (initialVelocity !== undefined && acceleration !== undefined && time !== undefined) {
var finalVelocity = (initialVelocity + acceleration * time);
document.getElementById('paragraphOne').innerHTML = 'The final Velocity is about equal to: ' + finalVelocity +' m/s';
}}
To obtain a real undefined value, you could use a function like:
function UndefinedIfEmpty(value)
{
if(value.trim() == "")
{
return undefined;
}
else
{
return value;
}
}
// Use it:
// var initialVelocity = UndefinedIfEmpty(document.getElementById('formInitialV').elements['initialVName'].value);
// and so on
console.log("`` is ", UndefinedIfEmpty(""));
console.log("` ` is ", UndefinedIfEmpty(" "));
console.log("`12` is ", UndefinedIfEmpty("12"));
You should even convert into number, to avoid: initialVelocity + acceleration * time => "12" + "4" * 13 => "12" + 52 => "1252" (string concatenation).
function NumberOrUndefined(value)
{
value = value.trim();
if ( value == "" )
{
return undefined;
}
else
{
return parseInt(value, 10);
}
}
// 10 in parseInt to avoid octal convertion
console.log("` ` is", NumberOrUndefined(" "));
console.log("12 is a ", typeof NumberOrUndefined("12"));

Why wont my closure function work?

The function below adds arguments within 1 paranthesis fine. For example, it computes addTogether(2,3) = 5 and addTogether(2,"3") = undefined.
However, it fails to compute addTogether(2)(3) = 5, instead giving me the error that "addTogether(...) is not a function". The closure function (return function(x)) is supposed to take into the second argument in addTogether(2)(3), and I'm lost on why it dos not work.
function addTogether() {
if (typeof arguments[0] !== "number" || typeof arguments[1] !== "number") {
return undefined;
} //not harmful but not necessary
var sum = 0;
var num = arguments[0];
if (arguments.length === 1) {
//if only 1 argument in the original function...
if (typeof arguments[0] !== "number") {
return undefined;
//returns undefined if arguments[0] isnt a number
}
return function(x) {
if (typeof arguments[0] !== "number") {
return undefined;
//in the closure/2nd function, if first argument isnt a number then no sum will be provided
} else {
sum = num + x; //x = second given argument
return sum;
}
};
}
if (typeof arguments[0] === "number" && typeof arguments[1] === "number") {
for (var x = 0; x < arguments.length; x++) {
if (typeof arguments[x] === "number") {
sum += arguments[x];
//add the argument[0] and [1] if both are number types, not string or array types or any other types
} else {
sum = undefined;
}
}
return sum;
}
// the above "if" statement is rsponsible for achieving addTogether(2,3) = 5;
}
console.log(addTogether(2)(3));
If you want your function to work like addTogether(2)(3), this means that your
addTogether must take an parameter and return a function. addTogether(2) this call will return a new function, and then call the returned function with the second parameter.
In your case when you compare
if (typeof arguments[0] !== "number" || typeof arguments[1] !== "number")
and call the function with one argument, the second typeof arguments[1] !== "number" returns you true, because the second parameter is undefined, so it is not a number and your function returns undefined.
And in your code you can remove some conditions also. Because the above condition will already check them.
function addTogether() {
if (typeof arguments[0] !== "number") {
return undefined;
}
var sum = 0;
var num = arguments[0];
if (arguments.length === 1) {
return function(x) {
if (typeof arguments[0] !== "number") {
return undefined;
} else {
sum = num + x;
return sum;
}
};
}
if (typeof arguments[0] === "number" && typeof arguments[1] === "number") {
for (var x = 0; x < arguments.length; x++) {
if (typeof arguments[x] === "number") {
sum += arguments[x];
} else {
sum = undefined;
}
}
return sum;
}
}
console.log(addTogether(2)(3));
if (typeof arguments[0] !== "number" || typeof arguments[1] !== "number") already causes addTogether(2) to return undefined.
Placing that if statement at the end of the function or turning that || into an && fixes it.

Categories