if statement many values check for same source, without repeated source - javascript

if(document.getElementById('TheId').value (>=5 && <=6))
{
//code here
}
instead of:
if(document.getElementById('TheId').value >=5 && document.getElementById('TheId').value <=6)
{
//code here
}
can this work ?! , and why not they make the condition easy like this because it points to the same source , any information ?

The condition can be written easily like that, you just have to extract the value to another variable first. Also, since .value returns a string, you probably want to cast it to a number first, just so that nothing unexpected occurs:
const value = Number(document.getElementById('TheId'));
if (value >= 5 && value <= 6) {
// do something
}
If you wanted to put it all inside the if parentheses, you could, but it would look really ugly, since you'd have to use the unintuitive comma operator:
if ((value = Number(document.getElementById('TheId')), (value >= 5 && value <= 6)) {
// do something
}
(much better to put the value into a variable beforehand)
I suppose another method would be to define two functions for testing the value, and check that everyone of the functions passes when passed the value:
if (
[val => val >= 5, val => val <= 6]
.every(
test => test(Number(document.getElementById('TheId'))
)
)
{
// do something
}
But putting the value into a variable beforehand makes much more sense.

Related

javascript object related query [duplicate]

Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
Moderator note: Please resist the urge to edit the code or remove this notice. The pattern of whitespace may be part of the question and therefore should not be tampered with unnecessarily. If you are in the "whitespace is insignificant" camp, you should be able to accept the code as is.
Is it ever possible that (a== 1 && a ==2 && a==3) could evaluate to true in JavaScript?
This is an interview question asked by a major tech company. It happened two weeks back, but I'm still trying to find the answer. I know we never write such code in our day-to-day job, but I'm curious.
If you take advantage of how == works, you could simply create an object with a custom toString (or valueOf) function that changes what it returns each time it is used such that it satisfies all three conditions.
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
The reason this works is due to the use of the loose equality operator. When using loose equality, if one of the operands is of a different type than the other, the engine will attempt to convert one to the other. In the case of an object on the left and a number on the right, it will attempt to convert the object to a number by first calling valueOf if it is callable, and failing that, it will call toString. I used toString in this case simply because it's what came to mind, valueOf would make more sense. If I instead returned a string from toString, the engine would have then attempted to convert the string to a number giving us the same end result, though with a slightly longer path.
I couldn't resist - the other answers are undoubtedly true, but you really can't walk past the following code:
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
console.log("Why hello there!")
}
Note the weird spacing in the if statement (that I copied from your question). It is the half-width Hangul (that's Korean for those not familiar) which is an Unicode space character that is not interpreted by ECMA script as a space character - this means that it is a valid character for an identifier. Therefore there are three completely different variables, one with the Hangul after the a, one with it before and the last one with just a. Replacing the space with _ for readability, the same code would look like this:
var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
console.log("Why hello there!")
}
Check out the validation on Mathias' variable name validator. If that weird spacing was actually included in their question, I feel sure that it's a hint for this kind of answer.
Don't do this. Seriously.
Edit: It has come to my attention that (although not allowed to start a variable) the Zero-width joiner and Zero-width non-joiner characters are also permitted in variable names - see Obfuscating JavaScript with zero-width characters - pros and cons?.
This would look like the following:
var a= 1;
var a‍= 2; //one zero-width character
var a‍‍= 3; //two zero-width characters (or you can use the other one)
if(a==1&&a‍==2&&a‍‍==3) {
console.log("Why hello there!")
}
IT IS POSSIBLE!
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a == 1 && a == 2 && a == 3)
console.log("wohoo");
}
This uses a getter inside of a with statement to let a evaluate to three different values.
... this still does not mean this should be used in real code...
Even worse, this trick will also work with the use of ===.
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a !== a)
console.log("yep, this is printed.");
}
Example without getters or valueOf:
a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);
This works because == invokes toString which calls .join for Arrays.
Another solution, using Symbol.toPrimitive which is an ES6 equivalent of toString/valueOf:
let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };
console.log(a == 1 && a == 2 && a == 3);
If it is asked if it is possible (not MUST), it can ask "a" to return a random number. It would be true if it generates 1, 2, and 3 sequentially.
with({
get a() {
return Math.floor(Math.random()*4);
}
}){
for(var i=0;i<1000;i++){
if (a == 1 && a == 2 && a == 3){
console.log("after " + (i+1) + " trials, it becomes true finally!!!");
break;
}
}
}
When you can't do anything without regular expressions:
var a = {
r: /\d/g,
valueOf: function(){
return this.r.exec(123)[0]
}
}
if (a == 1 && a == 2 && a == 3) {
console.log("!")
}
It works because of custom valueOf method that is called when Object compared with primitive (such as Number). Main trick is that a.valueOf returns new value every time because it's calling exec on regular expression with g flag, which causing updating lastIndex of that regular expression every time match is found. So first time this.r.lastIndex == 0, it matches 1 and updates lastIndex: this.r.lastIndex == 1, so next time regex will match 2 and so on.
This is possible in case of variable a being accessed by, say 2 web workers through a SharedArrayBuffer as well as some main script. The possibility is low, but it is possible that when the code is compiled to machine code, the web workers update the variable a just in time so the conditions a==1, a==2 and a==3 are satisfied.
This can be an example of race condition in multi-threaded environment provided by web workers and SharedArrayBuffer in JavaScript.
Here is the basic implementation of above:
main.js
// Main Thread
const worker = new Worker('worker.js')
const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let's use 2 workers
const sab = new SharedArrayBuffer(1)
modifiers.forEach(m => m.postMessage(sab))
worker.postMessage(sab)
worker.js
let array
Object.defineProperty(self, 'a', {
get() {
return array[0]
}
});
addEventListener('message', ({data}) => {
array = new Uint8Array(data)
let count = 0
do {
var res = a == 1 && a == 2 && a == 3
++count
} while(res == false) // just for clarity. !res is fine
console.log(`It happened after ${count} iterations`)
console.log('You should\'ve never seen this')
})
modifier.js
addEventListener('message' , ({data}) => {
setInterval( () => {
new Uint8Array(data)[0] = Math.floor(Math.random()*3) + 1
})
})
On my MacBook Air, it happens after around 10 billion iterations on the first attempt:
Second attempt:
As I said, the chances will be low, but given enough time, it'll hit the condition.
Tip: If it takes too long on your system. Try only a == 1 && a == 2 and change Math.random()*3 to Math.random()*2. Adding more and more to list drops the chance of hitting.
It can be accomplished using the following in the global scope. For nodejs use global instead of window in the code below.
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('yay');
}
This answer abuses the implicit variables provided by the global scope in the execution context by defining a getter to retrieve the variable.
This is also possible using a series of self-overwriting getters:
(This is similar to jontro's solution, but doesn't require a counter variable.)
(() => {
"use strict";
Object.defineProperty(this, "a", {
"get": () => {
Object.defineProperty(this, "a", {
"get": () => {
Object.defineProperty(this, "a", {
"get": () => {
return 3;
}
});
return 2;
},
configurable: true
});
return 1;
},
configurable: true
});
if (a == 1 && a == 2 && a == 3) {
document.body.append("Yes, it’s possible.");
}
})();
Alternatively, you could use a class for it and an instance for the check.
function A() {
var value = 0;
this.valueOf = function () { return ++value; };
}
var a = new A;
if (a == 1 && a == 2 && a == 3) {
console.log('bingo!');
}
EDIT
Using ES6 classes it would look like this
class A {
constructor() {
this.value = 0;
this.valueOf();
}
valueOf() {
return this.value++;
};
}
let a = new A;
if (a == 1 && a == 2 && a == 3) {
console.log('bingo!');
}
I don't see this answer already posted, so I'll throw this one into the mix too. This is similar to Jeff's answer with the half-width Hangul space.
var a = 1;
var a = 2;
var а = 3;
if(a == 1 && a == 2 && а == 3) {
console.log("Why hello there!")
}
You might notice a slight discrepancy with the second one, but the first and third are identical to the naked eye. All 3 are distinct characters:
a - Latin lower case A
a - Full Width Latin lower case A
а - Cyrillic lower case A
The generic term for this is "homoglyphs": different unicode characters that look the same. Typically hard to get three that are utterly indistinguishable, but in some cases you can get lucky. A, Α, А, and Ꭺ would work better (Latin-A, Greek Alpha, Cyrillic-A, and Cherokee-A respectively; unfortunately the Greek and Cherokee lower-case letters are too different from the Latin a: α,ꭺ, and so doesn't help with the above snippet).
There's an entire class of Homoglyph Attacks out there, most commonly in fake domain names (eg. wikipediа.org (Cyrillic) vs wikipedia.org (Latin)), but it can show up in code as well; typically referred to as being underhanded (as mentioned in a comment, [underhanded] questions are now off-topic on PPCG, but used to be a type of challenge where these sorts of things would show up). I used this website to find the homoglyphs used for this answer.
Yes, it is possible! 😎
» JavaScript
if‌=()=>!0;
var a = 9;
if‌(a==1 && a== 2 && a==3)
{
document.write("<h1>Yes, it is possible!😎</h1>")
}
The above code is a short version (thanks to #Forivin for its note in comments) and the following code is original:
var a = 9;
if‌(a==1 && a== 2 && a==3)
{
//console.log("Yes, it is possible!😎")
document.write("<h1>Yes, it is possible!😎</h1>")
}
//--------------------------------------------
function if‌(){return true;}
If you just see top side of my code and run it you say WOW, how?
So I think it is enough to say Yes, it is possible to someone that said to
you: Nothing is impossible
Trick: I used a hidden character after if to make a function that its name is similar to if. In JavaScript we can not override keywords so I forced to use this way. It is a fake if, but it works for you in this case!
» C#
Also I wrote a C# version (with increase property value technic):
static int _a;
public static int a => ++_a;
public static void Main()
{
if(a==1 && a==2 && a==3)
{
Console.WriteLine("Yes, it is possible!😎");
}
}
Live Demo
JavaScript
a == a +1
In JavaScript, there are no integers but only Numbers, which are implemented as double precision floating point numbers.
It means that if a Number a is large enough, it can be considered equal to four consecutive integers:
a = 100000000000000000
if (a == a+1 && a == a+2 && a == a+3){
console.log("Precision loss!");
}
True, it's not exactly what the interviewer asked (it doesn't work with a=0), but it doesn't involve any trick with hidden functions or operator overloading.
Other languages
For reference, there are a==1 && a==2 && a==3 solutions in Ruby and Python. With a slight modification, it's also possible in Java.
Ruby
With a custom ==:
class A
def ==(o)
true
end
end
a = A.new
if a == 1 && a == 2 && a == 3
puts "Don't do this!"
end
Or an increasing a:
def a
#a ||= 0
#a += 1
end
if a == 1 && a == 2 && a == 3
puts "Don't do this!"
end
Python
You can either define == for a new class:
class A:
def __eq__(self, who_cares):
return True
a = A()
if a == 1 and a == 2 and a == 3:
print("Don't do that!")
or, if you're feeling adventurous, redefine the values of integers:
import ctypes
def deref(addr, typ):
return ctypes.cast(addr, ctypes.POINTER(typ))
deref(id(2), ctypes.c_int)[6] = 1
deref(id(3), ctypes.c_int)[6] = 1
deref(id(4), ctypes.c_int)[6] = 1
print(1 == 2 == 3 == 4)
# True
It might segfault, depending on your system/interpreter.
The python console crashes with the above code, because 2 or 3 are probably used in the background. It works fine if you use less-common integers:
>>> import ctypes
>>>
>>> def deref(addr, typ):
... return ctypes.cast(addr, ctypes.POINTER(typ))
...
>>> deref(id(12), ctypes.c_int)[6] = 11
>>> deref(id(13), ctypes.c_int)[6] = 11
>>> deref(id(14), ctypes.c_int)[6] = 11
>>>
>>> print(11 == 12 == 13 == 14)
True
Java
It's possible to modify Java Integer cache:
package stackoverflow;
import java.lang.reflect.Field;
public class IntegerMess
{
public static void main(String[] args) throws Exception {
Field valueField = Integer.class.getDeclaredField("value");
valueField.setAccessible(true);
valueField.setInt(1, valueField.getInt(42));
valueField.setInt(2, valueField.getInt(42));
valueField.setInt(3, valueField.getInt(42));
valueField.setAccessible(false);
Integer a = 42;
if (a.equals(1) && a.equals(2) && a.equals(3)) {
System.out.println("Bad idea.");
}
}
}
This is an inverted version of #Jeff's answer* where a hidden character (U+115F, U+1160 or U+3164) is used to create variables that look like 1, 2 and 3.
var a = 1;
var ᅠ1 = a;
var ᅠ2 = a;
var ᅠ3 = a;
console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 );
* That answer can be simplified by using zero width non-joiner (U+200C) and zero width joiner (U+200D). Both of these characters are allowed inside identifiers but not at the beginning:
var a = 1;
var a‌ = 2;
var a‍ = 3;
console.log(a == 1 && a‌ == 2 && a‍ == 3);
/****
var a = 1;
var a\u200c = 2;
var a\u200d = 3;
console.log(a == 1 && a\u200c == 2 && a\u200d == 3);
****/
Other tricks are possible using the same idea e.g. by using Unicode variation selectors to create variables that look exactly alike (a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true).
Rule number one of interviews; never say impossible.
No need for hidden character trickery.
window.__defineGetter__( 'a', function(){
if( typeof i !== 'number' ){
// define i in the global namespace so that it's not lost after this function runs
i = 0;
}
return ++i;
});
if( a == 1 && a == 2 && a == 3 ){
console.log( 'Oh dear, what have we done?' );
}
Honestly though, whether there is a way for it to evaluate to true or not (and as others have shown, there are multiple ways), the answer I'd be looking for, speaking as someone who has conducted hundreds of interviews, would be something along the lines of:
"Well, maybe yes under some weird set of circumstances that aren't immediately obvious to me... but if I encountered this in real code then I would use common debugging techniques to figure out how and why it was doing what it was doing and then immediately refactor the code to avoid that situation... but more importantly: I would absolutely NEVER write that code in the first place because that is the very definition of convoluted code, and I strive to never write convoluted code".
I guess some interviewers would take offense to having what is obviously meant to be a very tricky question called out, but I don't mind developers who have an opinion, especially when they can back it up with reasoned thought and can dovetail my question into a meaningful statement about themselves.
If you ever get such an interview question (or notice some equally unexpected behavior in your code) think about what kind of things could possibly cause a behavior that looks impossible at first glance:
Encoding: In this case the variable you are looking at is not the one you think it is. This can happen if you intentionally mess around with Unicode using homoglyphs or space characters to make the name of a variable look like another one, but encoding issues can also be introduced accidentally, e.g. when copying & pasting code from the Web that contains unexpected Unicode code points (e.g. because a content management system did some "auto-formatting" such as replacing fl with Unicode 'LATIN SMALL LIGATURE FL' (U+FB02)).
Race conditions: A race-condition might occur, i.e. a situation where code is not executing in the sequence expected by the developer. Race conditions often happen in multi-threaded code, but multiple threads are not a requirement for race conditions to be possible – asynchronicity is sufficient (and don't get confused, async does not mean multiple threads are used under the hood).
Note that therefore JavaScript is also not free from race conditions just because it is single-threaded. See here for a simple single-threaded – but async – example. In the context of an single statement the race condition however would be rather hard to hit in JavaScript.
JavaScript with web workers is a bit different, as you can have multiple threads. #mehulmpt has shown us a great proof-of-concept using web workers.
Side-effects: A side-effect of the equality comparison operation (which doesn't have to be as obvious as in the examples here, often side-effects are very subtle).
These kind of issues can appear in many programming languages, not only JavaScript, so we aren't seeing one of the classical JavaScript WTFs here1.
Of course, the interview question and the samples here all look very contrived. But they are a good reminder that:
Side-effects can get really nasty and that a well-designed program should be free from unwanted side-effects.
Multi-threading and mutable state can be problematic.
Not doing character encoding and string processing right can lead to nasty bugs.
1 For example, you can find an example in a totally different programming language (C#) exhibiting a side-effect (an obvious one) here.
Here's another variation, using an array to pop off whatever values you want.
const a = {
n: [3,2,1],
toString: function () {
return a.n.pop();
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Yes');
}
Okay, another hack with generators:
const value = function* () {
let i = 0;
while(true) yield ++i;
}();
Object.defineProperty(this, 'a', {
get() {
return value.next().value;
}
});
if (a === 1 && a === 2 && a === 3) {
console.log('yo!');
}
Using Proxies:
var a = new Proxy({ i: 0 }, {
get: (target, name) => name === Symbol.toPrimitive ? () => ++target.i : target[name],
});
console.log(a == 1 && a == 2 && a == 3);
Proxies basically pretend to be a target object (the first parameter), but intercept operations on the target object (in this case the "get property" operation) so that there is an opportunity to do something other than the default object behavior. In this case the "get property" action is called on a when == coerces its type in order to compare it to each number. This happens:
We create a target object, { i: 0 }, where the i property is our counter
We create a Proxy for the target object and assign it to a
For each a == comparison, a's type is coerced to a primitive value
This type coercion results in calling a[Symbol.toPrimitive]() internally
The Proxy intercepts getting the a[Symbol.toPrimitive] function using the "get handler"
The Proxy's "get handler" checks that the property being gotten is Symbol.toPrimitive, in which case it increments and then returns the counter from the target object: ++target.i. If a different property is being retrieved, we just fall back to returning the default property value, target[name]
So:
var a = ...; // a.valueOf == target.i == 0
a == 1 && // a == ++target.i == 1
a == 2 && // a == ++target.i == 2
a == 3 // a == ++target.i == 3
As with most of the other answers, this only works with a loose equality check (==), because strict equality checks (===) do not do type coercion that the Proxy can intercept.
Actually the answer to the first part of the question is "Yes" in every programming language. For example, this is in the case of C/C++:
#define a (b++)
int b = 1;
if (a ==1 && a== 2 && a==3) {
std::cout << "Yes, it's possible!" << std::endl;
} else {
std::cout << "it's impossible!" << std::endl;
}
Same, but different, but still same (can be "tested" multiple times):
const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
My idea started from how Number object type equation works.
An ECMAScript 6 answer that makes use of Symbols:
const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));
Due to == usage, JavaScript is supposed to coerce a into something close to the second operand (1, 2, 3 in this case). But before JavaScript tries to figure coercing on its own, it tries to call Symbol.toPrimitive. If you provide Symbol.toPrimitive JavaScript would use the value your function returns. If not, JavaScript would call valueOf.
I think this is the minimal code to implement it:
i=0,a={valueOf:()=>++i}
if (a == 1 && a == 2 && a == 3) {
console.log('Mind === Blown');
}
Creating a dummy object with a custom valueOf that increments a global variable i on each call. 23 characters!
This one uses the defineProperty with a nice side-effect causing global variable!
var _a = 1
Object.defineProperty(this, "a", {
"get": () => {
return _a++;
},
configurable: true
});
console.log(a)
console.log(a)
console.log(a)
By overriding valueOf in a class declaration, it can be done:
class Thing {
constructor() {
this.value = 1;
}
valueOf() {
return this.value++;
}
}
const a = new Thing();
if(a == 1 && a == 2 && a == 3) {
console.log(a);
}
What happens is that valueOf is called in each comparison operator. On the first one, a will equal 1, on the second, a will equal 2, and so on and so forth, because each time valueOf is called, the value of a is incremented.
Therefore the console.log will fire and output (in my terminal anyways) Thing: { value: 4}, indicating the conditional was true.
As we already know that the secret of loose equality operator (==) will try to convert both values to a common type. As a result, some functions will be invoked.
ToPrimitive(A) attempts to convert its object argument to a primitive
value, by invoking varying sequences of A.toString and A.valueOf
methods on A.
So as other answers using Symbol.toPrimitive, .toString, .valueOf from integer. I would suggest the solution using an array with Array.pop like this.
let a = { array: [3, 2, 1], toString: () => a.array.pop() };
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
In this way, we can work with text like this
let a = { array: ["World", "Hello"], toString: () => a.array.pop() };
if(a == "Hello" && a == "World") {
console.log('Hello World!');
}
Surprisingly, yes. The == loose equality operator in JS calls the valueOf() method of the object that's being compared. Therefore, you can create a class that returns an internal value, then increments that interval value every time it's called. Like this:
class AClass {
constructor(initalVal) {
this.val = initalVal;
}
valueOf() {
return this.val++;
}
}
const a = new AClass(1);
console.log(a==1 && a==2 && a==3)
I know that there are a lot of other answers to this question, but this is how you'd do it with ES6 syntax.
Note: If you don't want this to happen, then you should use the === operator to check for strict instead. Like this:
class AClass {
constructor(initalVal) {
this.val = initalVal;
}
valueOf() {
return this.val++;
}
}
const a = new AClass(1);
console.log(a===1 && a===2 && a===3)
Yes, you can Do that, see the following JavaScript code:
let a = 0 // Create a variable and give it a value
if( a !== 1 && a !== 2 && a !== 3 )
{
console.log("true")
}
Explanation of the solution:
Simply , we add the not equal sign
before the == sign so that we tell the language that these values are
not equal to the value in the variable

How to check if less than 2 of 3 variables are empty

I need to check that there are at least 2 values before running a script, but can't seem to get the condition to fire.
When I use if (risForm) {... the script runs when risForm is filled, and when I use if (!(risForm)) {... the script runs if risForm is empty, but I can't seem to work out how to check if any 2 of the three is full... I've tried this:
if ((!(risForm)) + (!(runForm)) + (!(angForm)) < 2) {...
along with a numerous adjustments to precise formatting/bracketting, but it's not getting me anywhere!
Make an array of the variables, filter by Boolean, then check the length of the array:
const forms = [risForm, runForm, angForm];
if (forms.filter(Boolean).length < 2) {
throw new Error('Not enough forms are filled');
}
// rest of the code
You can avoid creating an intermediate array by using reduce instead, if you wanted:
const filledFormCount = forms.reduce((a, form) => a + Boolean(form), 0);
if (filledFormCount < 2) {
throw new Error('Not enough forms are filled');
}
If you can have all your variables inside an array, you can do
yourArray.filter(Boolean).length >= 2
To break it apart, let's rewrite the above in a more verbose fashion:
yourArray
.filter(
function (variable) {
return Boolean(variable)
}
)
.length >= 2
Now, array.filter() gets every variable in the array and runs each as the argument for the function inside the parens, in this case: Boolean(). If the return value is truthy, the variable is "filtered in", if not it is "filtered out". It then returns a new array without the variables that were filtered out.
Boolean() is a function that will coerce your value into either true or false. If there's a value in the variable, it will return true... But there's a catch: it will return false for zeroes and empty strings - beware of that.
Finally, we use .length to count how many variables were "filtered in" and, if it's more than two, you can proceed with the code.
Maybe this pseudo code can illustrate it better:
const variables = ['foo', undefined, 'bar'];
variables.filter(Boolean).length >= 2;
['foo', undefined, 'bar'].filter(Boolean).length >= 2;
keepIfTruthy(['foo' is truthy, undefined is falsy, 'bar' is truthy]).length >= 2;
['foo', 'bar'].length >= 2;
2 >= 2;
true;
Javascript's true and false are useful here because when coerced to a number, they become respectively 1 and 0. So...
function foo(a,b,c) {
const has2of3 = !!a + !!b + !!c;
if ( has2of3 ) {
// Do something useful here
}
}
One caveat, though is that the empty string '' and 0 are falsy, which means they would be treated as not present. If that is an issue, you could do something like this:
function foo(a,b,c) {
const hasValue = x => x !== undefined && x !== null;
const has2of3 = hasValue(a) + hasValue(b) + hasValue(c);
if ( has2of3 ) {
// Do something useful here
}
}
let risForm = "a",
runForm = "",
angForm = "";
let arr = [risForm, runForm, angForm]
let res = arr.filter(el => !el || el.trim() === "").length <= 1
console.log(res)
There many ways to solve this. Lets try with basic idea. You want to make a reusable code and something that support multiple variables, also condition value might change. This means, we need to define an array of the form values and a condition value to verify. Then we can apply a function to verify the condition. So let's try some code:
let risForm, runForm, angForm;
risForm = 'Active';
// runForm = 3;
const formValues = [risForm, runForm, angForm];
const minFilledForms = 2;
const hasValue = a => !!a && a !== undefined && a !== null;
verifyForms();
function verifyForms() {
let filledForms = formValues.reduce((count, form) => count + hasValue(form), 0);
if (filledForms < minFilledForms) {
console.log(`Only ${filledForms} of ${formValues.length} forms have filled. Minimum ${minFilledForms} forms are requiered.`);
}
console.log('Continue...');
}

Filter an array of objects using the filter method with multiple tests

I'd like to filter an array of objects based on multiple tests. For this example, I want to filter an array of objects if the values for the keys aren't null, and that one value for one key is less than 90. I'm currently doing this with a for loop like so:
let filtered = []
for (let i = 0; i < articles.length; i++) {
if (articles[i].title !== null && articles[i].title.length <= 90 &&
articles[i].date !== null &&
articles[i].image !== null &&
articles[i].description !== null &&
articles[i].link !== null) {
filtered.push(articles[i])
}
}
But it's pretty clumpy and I know the filter method can achieve something similar. But I'm unsure if it can check multiple keys and their values with the same test whilst checking if a specific value passes an independent test too.
Try:
articles.filter(article =>
Object.values(article).every(x => (x !== null))
&& article.title.length <= 90
)
Let's break this down:
articles.filter(article => ...)
.filter is a function property of type that accepts a callback argument, which it calls for each item. Essentially, we're passing it a function - not executing it right away, which it can call at its leisure. It's sort of like:
let a = alert;
We're not calling the alert function, we're just saving it to a variable. In the case of .filter, we're using it as a pseudo-variable - an argument. Internally, all .filter is doing is:
Array.prototype.filter(callbackFunc) {
newArr = [];
for (i=0;i<this.length;i++){
if (callbackFunc(this[i]) === false){ // We're calling `callbackFunc` manually, for each item in the loop.
newArr.push(this[i]);
}
}
return newArr;
}
The next bit to explain is the actual callback function we're using. It's defined with ES6 arrow syntax, but it's the equivalent of:
articles.filter(function(article){
return Object.values(article).every(x => (x !== null))
&& article.title.length <= 90
})
The first line of the callback function, Object.values(article).every(x => (x !== null)), can be broken down to:
let values = Object.values(article); // Get the value of all of the keys in the object
function checkFunction(item){ // Define a helper function
return (x !== null); // Which returns if an item is _not_ null.
}
let result = values.every(checkFunction); // Run `checkFunction` on every item in the array (see below), and ensure it matches _all_ of them.
Finally, we just need to clarify what every does. It's another example of functional JS, where functions accept callback functions as parameters. The internal code looks like this:
Array.prototype.every(callbackFunc) {
for (i=0;i<this.length;i++){
if (callbackFunc(this[i]) === false){ // We're calling `callbackFunc` manually, for each item in the loop.
return false;
}
}
// In JS, returning a value automatically stops execution of the function.
// So this line of code is only reached if `return false` is never met.
return true;
}
And && article.title.length <= 90 should hopefully be self-explanatory: while .every returns a boolean value (true or false), a true will only be returned by the callback function to the filter if the second condition is also met, i.e if the every returns true and article.title.length <= 90
The filter method does exactly this: it takes a conditional (just like that in your if statement and adds it to the array if the condition is met. Your code almost matches the filter syntax exactly, actually:
let filtered = articles.filter(article =>
article.title !== null
article.title.length <= 90 &&
article.date !== null &&
article.image !== null &&
article.description !== null &&
article.link !== null);
yes filter can do this, it just takes a function and applies it to each item in the array
array.filter(x => x.title != null && ... etc)
the examples in this section is pretty much what you are doing https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Filtering_invalid_entries_from_JSON

How to check if a value is not null and not empty string in JS

Is there any check if a value is not null and not empty string in Javascript? I'm using the following one:
var data; //get its value from db
if(data != null && data != '') {
// do something
}
But I'm wondering if there is another better solution. Thanks.
If you truly want to confirm that a variable is not null and not an empty string specifically, you would write:
if(data !== null && data !== '') {
// do something
}
Notice that I changed your code to check for type equality (!==|===).
If, however you just want to make sure, that a code will run only for "reasonable" values, then you can, as others have stated already, write:
if (data) {
// do something
}
Since, in javascript, both null values, and empty strings, equals to false (i.e. null == false).
The difference between those 2 parts of code is that, for the first one, every value that is not specifically null or an empty string, will enter the if. But, on the second one, every true-ish value will enter the if: false, 0, null, undefined and empty strings, would not.
Instead of using
if(data !== null && data !== '' && data!==undefined) {
// do something
}
You can use below simple code
if(Boolean(value)){
// do something
}
Values that are intuitively “empty”, like 0, an empty string, null, undefined, and NaN, become false
Other values become true
Both null and an empty string are falsy values in JS. Therefore,
if (data) { ... }
is completely sufficient.
A note on the side though: I would avoid having a variable in my code that could manifest in different types. If the data will eventually be a string, then I would initially define my variable with an empty string, so you can do this:
if (data !== '') { ... }
without the null (or any weird stuff like data = "0") getting in the way.
if (data?.trim().length > 0) {
//use data
}
the ?. optional chaining operator will short-circuit and return undefined if data is nullish (null or undefined) which will evaluate to false in the if expression.
I often test for truthy value and also for empty spaces in the string:
if(!(!data || data.trim().length === 0)) {
// do something here
}
If you have a string consisting of one or more empty spaces it will evaluate to true.
Simple solution to check if string is undefined or null or "":-
const value = null;
if(!value) {
console.log('value is either null, undefined or empty string');
}
Both null and empty could be validated as follows:
<script>
function getName(){
var myname = document.getElementById("Name").value;
if(myname != '' && myname != null){
alert("My name is "+myname);
}else{
alert("Please Enter Your Name");
}
}
try it----------
function myFun(){
var inputVal=document.getElementById("inputId").value;
if(inputVal){
document.getElementById("result").innerHTML="<span style='color:green'>The value is "+inputVal+'</span>';
}
else{
document.getElementById("result").innerHTML="<span style='color:red'>Something error happen! the input May be empty.</span>";
}
}
<input type="text" id="inputId">
<input type="button" onclick="myFun()" value="View Result">
<h1 id="result"></h1>
I got so fed up with checking for null and empty strings specifically, that I now usually just write and call a small function to do it for me.
/**
* Test if the given value equals null or the empty string.
*
* #param {string} value
**/
const isEmpty = (value) => value === null || value === '';
// Test:
isEmpty(''); // true
isEmpty(null); // true
isEmpty(1); // false
isEmpty(0); // false
isEmpty(undefined); // false
When we code empty in essence could mean any one of the following given the circumstances;
0 as in number value
0.0 as in float value
'0' as in string value
'0.0' as in string value
null as in Null value, as per chance it could also capture undefined or it may not
undefined as in undefined value
false as in false truthy value, as per chance 0 also as truthy but what if we want to capture false as it is
'' empty sting value with no white space or tab
' ' string with white space or tab only
In real life situation as OP stated we may wish to test them all or at times we may only wish to test for limited set of conditions.
Generally if(!a){return true;} serves its purpose most of the time however it will not cover wider set of conditions.
Another hack that has made its round is return (!value || value == undefined || value == "" || value.length == 0);
But what if we need control on whole process?
There is no simple whiplash solution in native core JavaScript it has to be adopted. Considering we drop support for legacy IE11 (to be honest even windows has so should we) below solution born out of frustration works in all modern browsers;
function empty (a,b=[])
{if(!Array.isArray(b)) return;
var conditions=[null,'0','0.0',false,undefined,''].filter(x => !b.includes(x));
if(conditions.includes(a)|| (typeof a === 'string' && conditions.includes(a.toString().trim())))
{return true;};
return false;};`
Logic behind the solution is function has two parameters a and b, a is value we need to check, b is a array with set conditions we need to exclude from predefined conditions as listed above. Default value of b is set to an empty array [].
First run of function is to check if b is an array or not, if not then early exit the function.
next step is to compute array difference from [null,'0','0.0',false,undefined,''] and from array b. if b is an empty array predefined conditions will stand else it will remove matching values.
conditions = [predefined set] - [to be excluded set]
filter function does exactly that make use of it.
Now that we have conditions in array set all we need to do is check if value is in conditions array.
includes function does exactly that no need to write nasty loops of your own let JS engine do the heavy lifting.
Gotcha
if we are to convert a into string for comparison then 0 and 0.0 would run fine however Null and Undefined would through error blocking whole script. We need edge case solution. Below simple || covers the edge case if first condition is not satisfied. Running another early check through include makes early exit if not met.
if(conditions.includes(a)|| (['string', 'number'].includes(typeof a) && conditions.includes(a.toString().trim())))
trim() function will cover for wider white spaces and tabs only value and will only come into play in edge case scenario.
Play ground
function empty (a,b=[]){
if(!Array.isArray(b)) return;
conditions=[null,'0','0.0',false,undefined,''].filter(x => !b.includes(x));
if(conditions.includes(a)||
(['string', 'number'].includes(typeof a) && conditions.includes(a.toString().trim()))){
return true;
}
return false;
}
console.log('1 '+empty());
console.log('2 '+empty(''));
console.log('3 '+empty(' '));
console.log('4 '+empty(0));
console.log('5 '+empty('0'));
console.log('6 '+empty(0.0));
console.log('7 '+empty('0.0'));
console.log('8 '+empty(false));
console.log('9 '+empty(null));
console.log('10 '+empty(null,[null]));
console.log('11 dont check 0 as number '+empty(0,['0']));
console.log('12 dont check 0 as string '+empty('0',['0']));
console.log('13 as number for false as value'+empty(false,[false]));
Lets make it complex - what if our value to compare is array its self and can be as deeply nested it can be. what if we are to check if any value in array is empty, it can be an edge business case.
function empty (a,b=[]){
if(!Array.isArray(b)) return;
conditions=[null,'0','0.0',false,undefined,''].filter(x => !b.includes(x));
if(Array.isArray(a) && a.length > 0){
for (i = 0; i < a.length; i++) { if (empty(a[i],b))return true;}
}
if(conditions.includes(a)||
(['string', 'number'].includes(typeof a) && conditions.includes(a.toString().trim()))){
return true;
}
return false;
}
console.log('checking for all values '+empty([1,[0]]));
console.log('excluding for 0 from condition '+empty([1,[0]], ['0']));
it simple and wider use case function that I have adopted in my framework;
Gives control over as to what exactly is the definition of empty in a given situation
Gives control over to redefine conditions of empty
Can compare for almost for every thing from string, number, float, truthy, null, undefined and deep arrays
Solution is drawn keeping in mind the resuability and flexibility. All other answers are suited in case if simple one or two cases are to be dealt with. However, there is always a case when definition of empty changes while coding above snippets make work flawlessly in that case.
function validateAttrs(arg1, arg2, arg3,arg4){
var args = Object.values(arguments);
return (args.filter(x=> x===null || !x)).length<=0
}
console.log(validateAttrs('1',2, 3, 4));
console.log(validateAttrs('1',2, 3, null));
console.log(validateAttrs('1',undefined, 3, 4));
console.log(validateAttrs('1',2, '', 4));
console.log(validateAttrs('1',2, 3, null));

Javascript If Else always picks option 1

So my Javascript code is supposed to randomly pick, but it always picks the first option, even if I switch the options, it always goes to the one on top. Did I make an error, or how can I get this to work?
function test() {
var values = ["1","2"],
valueToUse = values[Math.floor(Math.random() * values.length)];
// do something with the selected value
alert(valueToUse);
}
if (values = 1) {
window.location = "tail.html"; }
else if (values = 2) { window.location = "head.html"; }
if (values = 1) {
That's an assignment, not a comparison (===). It will always be true.
Additionally, you never call test().
Additionally, you should be testing valueToUse not values, since that is where you assign your random choice.
Additionally, both valueToUse and values are locally scoped to the test() function and are not available outside it. Your assignment creates a new, global variable.
You need to use == (or ===) instead of =.
if (values == 1) {
// and so on...
}
To make your code fly, you could return a random selected value from the array, store it in value and check it for the new direction. I omit window.location and us simply console.log for displaying the result of the comparison.
The comparison is strict, with a check for a string.
function test() {
var values = ["1", "2"],
valueToUse = values[Math.floor(Math.random() * values.length)];
return valueToUse;
}
var value = test();
if (value === '1') {
console.log( "tail.html");
} else if (value === '2') {
console.log( "head.html");
}
Well, for the start if (values = 1) is not the valid way to compare.
= annotates assignment so basically you are setting the value to 1. If you want to compare values in js, you do it this way if (values === 1).
In other programming language u usually use == instead however in js if you compare it this way it will only check the value not the type of the variable so a number 2 will match a string "2"
if (2 == "2") {//result is true}.
If you use === it will check both the value and the type
if (2 == "2") {//result is false}

Categories

Resources