JavaScript set boolean by separate conditions? - javascript

I need to design a global boolean with 2 conditions a and b such that if A is ever true, the boolean is true until b is true, at which point the boolean is false. In other words, if A becomes false the boolean remains true.
I tried a straightforward global variable but it became false when A became false.
Preferably JavaScript, but pseudocode would be almost as helpful.

This sounds like an XOR. i.e.
!A and !B == false
A and !B == true
!A and B == true
A and B == false
Unfortunately, JavaScript doesn't have a logical XOR operator, however
if( A ? !B : B ) {
is functionally equivalent

If I understand your question correctly, it should be fairly easy to match those cases with
var bool = (a != b);
/*
(false != false) = false
(true != false) = true
(false != true) = true
(true != true) = false
*/
With your changes, you could create a global variable var aWasEverTrue = a; and then instead of setting a directly, use a function such as setA(true).
var a = false;
var b = false;
var aWasEverTrue = a;
function setA(newAValue) {
aWasEverTrue = true;
a = newAValue;
}
// (aWasEverTrue != b) = false
setA(true);
// (aWasEverTrue != b) = true
b = true;
// (aWasEverTrue != b) = false
setA(false);
// (aWasEverTrue != b) = false (as aWasEverTrue is still true)
b = false
// (aWasEverTrue != b) = true

What you want is a state machine
States for result:
T (True)
F (False)
Transitions:
F -- a (true) --> T
F -- anything else --> F
T -- b (true) --> F
T -- anything else --> T
You can express it with a series of ifs

Javascript old-school way:
function Enjoy() {
this.a = true;
this.b = true;
this.bool = true;
}
Enjoy.prototype = {
constructor: Enjoy,
setA: function( val ) {
this.a = val;
if ( this.a === true && this.b === true ) this.bool = false;
else if ( this.a === true && this.b === false ) this.bool = true;
},
setB: function( val ) {
this.b = val;
if ( this.a === true && this.b === true ) this.bool = true;
else if ( this.a === true && this.b === false ) this.bool = false;
},
getBool: function() {
return this.bool;
}
};
var enjoy = new Enjoy();
enjoy.getBool(); // true
enjoy.setB( false );
enjoy.getBool(); // false
As you can see, the idea is to use getters/setters for your boolean and both a and b variables where you do all your logic.
By the way, this question is definitely for StackOverflow.

Based on some assumptions about how B should behave if A has not been true:
function FlipFlop(){
this.latch = false;
this.value = false;
}
FlipFlop.prototype = {
constructor: FlipFlop,
setA: function( val ) {
this.latch = this.latch || !!val;
this.value = this.latch;
},
setB: function( val ) {
if(this.latch && !!val) {
this.latch = false;
}
this.value = !val;
},
getVal: function() {
return this.value;
}
}

Related

Profiling performance-sensitive code paths

I have a function that receives 2 arguments and 1 additional, optional argument. The function must return true if the first argument is bigger than the second one, false if not, except if the third argument is true (the third argument can be only true or false, false by default), in which case the function should return true if the first argument is either bigger or equal (strict comparison) to the second argument.
The function isn't guaranteed to receive arguments of the same type, or even arguments that make any sense (the function could be called with null, undefined). Anyways, the function must obey javascript behavior to compare the received arguments.
I have two functions, and I believe the second one should be faster, but neither my own benchmarks nor jsperf results say so. In fact, the first function is ~30-35% faster, which is quite a lot.
How can I track down the slow code paths inside each function? How can I know why the second function is slower?
This is my benchmark:
var microtime = require('microtime');
/* Helper functions */
function maybeBool() {
if(Math.round(Math.random() * 1)) {
return true;
} else {
return false;
}
}
function maybeNullUndef() {
if(Math.round(Math.random() * 1)) {
return null;
} else {
return undefined;
}
}
function randomString() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
}
function randomDate() {
var y = Math.round(Math.random() * 100);
return new Date(y);
}
function something() {
var x = Math.round(Math.random()*3);
switch(x) {
case 0:
return maybeBool();
break;
case 1:
return maybeNullUndef();
break;
case 2:
return randomString();
break;
case 3:
return randomDate();
break;
}
}
var things_to_compare = [];
for(i = 0; i < 500000; i++) {
var a = something();
var b = something();
things_to_compare.push([a, b]);
}
/* First function */
function gtHelper(prop1, prop2, equal) {
// 'falsy' and Boolean handling
if (!prop1 || !prop2 || prop1 === true || prop2 === true) {
if ((prop1 === true || prop1 === false) && (prop2 === true || prop2 === false)) {
if (equal) {
return prop1 === prop2;
} else {
if (prop1) {
return !prop2;
} else {
return false;
}
}
}
if (prop1 === undefined || prop1 === null || prop1 === false || prop2 === true) {
return !!equal || false;
}
if (prop2 === undefined || prop2 === null || prop1 === true || prop2 === false) {
return true;
}
if (prop1 > prop2) {
return true;
}
if (prop1 < prop2) {
return false;
}
// not lt and and not gt so equality assumed-- this ordering of tests is date compatible
return equal;
}
if (prop1 > prop2) {
return true;
}
if (prop1 < prop2) {
return false;
}
// not lt and and not gt so equality assumed-- this ordering of tests is date compatible
return equal;
}
/* Second function */
function gtHelper2 (prop1, prop2, equal) {
equal = !!equal;
//If 'prop1' is any of those, the result will be always 'false',
//unless 'equal' is true.
switch (prop1) {
case "":
case null:
case false:
case undefined:
return (prop1 === prop2 && equal);
}
//If 'prop2' is any of those, the result will be always 'true'
switch (prop2) {
case "":
case null:
case false:
case undefined:
return true;
}
if (prop1 > prop2 || (prop1 === prop2 && equal)) {
return true;
} else if (prop1 < prop2) {
return false;
} else {
return equal;
}
}
/* Benchmark */
var res1 = 0;
for(n = 0; n < 30; n++) {
var now = microtime.now();
for(i = 0; i < 500000; i++) {
gtHelper(things_to_compare[i][0], things_to_compare[i][1]);
}
var now1 = microtime.now();
res1 += now1 - now;
}
var res2 = 0;
for(n = 0; n < 30; n++) {
var now = microtime.now();
for(i = 0; i < 500000; i++) {
gtHelper2(things_to_compare[i][0], things_to_compare[i][1]);
}
var now1 = microtime.now();
res2 += now1 - now;
}
console.log("gtHelper:", res1/30);
console.log("gtHelper2:", res2/30);
Edit:
I have been further working on the second function, I achieved make it a little bit faster, but it keep lagging behind the first function.
This is how it looks now:
function gtHelper2 (prop1, prop2, equal) {
//If 'prop1' is any of those, the result will be always 'false',
//unless 'equal' is true.
if (!prop1) {
return (prop1 === prop2 && !!equal);
}
//If 'prop2' is any of those, the result will be always 'true'
if (!prop2) {
return true;
}
if (prop1 > prop2) {
return true;
} else if (prop1 < prop2) {
return false;
} else if (prop1 === prop2 && !!equal) {
return true;
} else {
return !!equal;
}
}
Your two functions do not return the same thing.
gtHelper(true, 'string') // true
gtHelper2(true, 'string') // false
gtHelper('string', new Date()) // undefined
gtHelper2('string', new Date()) // false
gtHelper(new Date(), 'string') // undefined
gtHelper2(new Date(), 'string') // false
If you can get these functions behaving the same, I am sure you will see more meaningful results.
You should be aware that, in the browser at least, you should not expect switch to perform the same on all platforms. You should read the ECMA spec on switch to see why optimising this should be so difficult. I know that Firefox did spend a good deal of time on making their switch implementation perform well. I've heard nothing about anything similar on V8.

Javascript Difference Between x=10; if(x) and if(x===10)

I understand that in terms of boolean
x = true;
if(x) //This is the same as if(x === True)
doSomething();
But if one were to set x to a number, then what does the if condition mean?
Does the condition mean if(x === true)? If so, why is that?
In javascript the below are falsey
false
undefined
null
0
""
NaN
Anything except the above are truthy, including numbers, except 0. So 10 is a truthy value and hence the if block, executes.
in short is as follows:
//!length = if(x.length);
var a; //undefined == if(!a) == !length
var b = ""; //void == if(!b)
var c = " "; //blank == if(c) == length
var d = "text"; //there == if(d) == length
var e = true; //true == true == if(e)
var f = false; //false == false == if(!f)
var g = null; //false == if(!g) == !length
var h = 0; //0 == if(!h)
var i = 1; //true == if(i)
var j = 0/0; //NaN == if(!j)
var k = document.body; // == if(k)
var l = document.getElementById("nothing"); // if(!l) == !length
Javascript is very flexible with regards to checking for "null" values. I'm guessing you're actually looking for empty strings, in which case this simpler code will work:
if(!blah){
Which will check for empty strings (""), null, undefined, false and the numbers 0 and NaN
var a; //undefined == if(!a) == !length
var b = ""; //void == if(!b)
var c = " "; //blank == if(c) == length
var d = "text"; //there == if(d) == length
var e = true; //true == true == if(e)
var f = false; //false == false == if(!f)
var g = null; //false == if(!g) == !length
var h = 0; //0 == if(!h)
var i = 1; //true == if(i)
var j = 0/0; //NaN == if(!j)
var k = document.body; // == if(k)
var l = document.getElementById("nothing"); // if(!l) == !length
consoletotal(l);
function consoletotal(bb){
consolea(bb);
consoleb(bb);
consolec(bb);
consoled(bb);
consolee(bb);
}
function consolea(bb){
if(bb){
console.log("yes" + bb);
}
}
function consoleb(bb){
if(bb===true){
console.log("true" + bb);
}
}
function consolec(bb){
if(bb===false){
console.log("false" + bb);
}
}
function consoled(bb){
if(!bb){
console.log("no" + bb);
}
}
function consolee(bb){
if(bb.length){
console.log("length" + bb);
}
}

compare three variable using java script

Hi I have three dynamic variable
my below code is working to check if all are equal
if ((a == b) && (b == c)) {
// they're all equal ...
}
But, I want to create a function passing three variable to check if any one variable is equal to other variable.
a=1;b=2;c=1;
isEqual = compareVariable(a,b,c);
here isEqual should be true .
How to create this function
function compareVariable(a,b,c) {
return a==b || b==c || c==a;
}
Try using it like this:
function compareVariable(a,b,c){
var a = a;
var b = b;
var c = c;
if ((a == b) && (b == c)) {
return true
}
else
{
return false;
}
}
compareVariable(1,2,3);
function compareVariable(a,b,c)
{
if ((a == b) || (b == c) || (a == c) ) {
alert("equal");
// they're all equal ...
}
else
{
alert("notequal");
}
}
Try this:
function compareVariable(a,b,c){
if ((a == b) || (b == c) || (a == c)) {
return true
// any or all equal
}
else
{
return false;
// if none of two is equal
}
}
To create a function you need to use the reserved keyword 'function' followed by the name of the function. In this case:
function compareVariable(a,b,c) {
return ((a == b) || (b == c) || (a == c));
}
This function will take your three variables and return boolean true if all the variables are the same.

JavaScript: Check to see if a variable or object exists

I have a function to return if a variable/object is set or not:
function isset() {
var a = arguments, l = a.length;
if (l === 0) { console.log("Error: isset() is empty"); }
for (var i=0; i<l; i++) {
try {
if (typeof a[i] === "object") {
var j=0;
for (var obj in a[i]) { j++; }
if (j>0) { return true; }
else { return false; }
}
else if (a[i] === undefined || a[i] === null) { return false; }
}
catch(e) {
if (e.name === "ReferenceError") { return false; }
}
}
return true;
}
For example, this works:
var foo;
isset(foo); // Returns false
foo = "bar";
isset(foo); // Returns true
foo = {};
isset(foo); // Returns false
isset(foo.bar); // Returns false
foo = { bar: "test" };
isset(foo); // Returns true
isset(foo.bar); // Returns true
Here is the problem... if foo is never set to begin with, this happens:
// foo has not been defined yet
isset(foo); // Returns "ReferenceError: foo is not defined"
I thought I could use try/catch/finally to return false if error.name === "ReferenceError" but it isn't working. Where am I going wrong?
Edit:
So the answer below is correct. As I expected, you cannot access an undefined variable or trap it with try/catch/finally (see below for an explanation).
However, here is a not so elegant solution. You have to pass the name of the variable in quotes, then use eval to do the checking. It's ugly, but it works:
// Usage: isset("foo"); // Returns true or false
function isset(a) {
if (a) {
if (eval("!!window."+a)) {
if (eval("typeof "+a+" === 'object'")) { return eval("Object.keys("+a+").length > 0") ? true : false; }
return (eval(a+" === undefined") || eval(a+" === null") || eval(a+" === ''")) ? false : true;
}
else { return false; }
}
else { console.log("Empty value: isset()"); }
}
And just to follow up some more, I cleaned up the original function at the very top. It still has the same problem where if the variable doesn't exist you get a ReferenceError, but this version is much cleaner:
// Usage: isset(foo); // Returns true or false if the variable exists.
function isset(a) {
if (a) {
if (typeof a === "object") { return Object.keys(a).length > 0 ? true : false; }
return (a === undefined || a === null || a === "") ? false : true;
}
else { console.log("Empty value: isset()"); }
}
You just can't do that type of check with a function. In order to pass the variable, it needs to exist, so it will fail before your code can run.
When you call it on the undeclared variable, you're attempting to resolve the value of the identifier in the argument position.
// v----resolve identifier so it can be passed, but resolution fails
isset(foo);
And of course, it doesn't exist, so the ReferenceError is thrown.
JavaScript doesn't have pointers, so there's nothing like a nil pointer that can be passed in its place.
You cannot pass a identifier that hasn't been initialised. You could pass a string, and an object to test, like the following:
function isset(str, obj) {
return obj[str] ? true : false;
}
isset("foo", window); // >>> false

How to check if two vars have the same reference?

How can you check if two or more objects/vars have the same reference?
You use == or === :
var thesame = obj1===obj2;
From the MDN :
If both operands are objects, then JavaScript compares internal
references which are equal when operands refer to the same object in
memory.
The equality and strict equality operators will both tell you if two variables point to the same object.
foo == bar
foo === bar
For reference type like objects, == or === operators check its reference only.
e.g
let a= { text:'my text', val:'my val'}
let b= { text:'my text', val:'my val'}
here a==b will be false as reference of both variables are different though their content are same.
but if I change it to
a=b
and if i check now a==b then it will be true , since reference of both variable are same now.
As from ES2015, a new method Object.is() has been introduced that can be used to compare and evaluate the sameness of two variables / references:
Below are a few examples:
Object.is('abc', 'abc'); // true
Object.is(window, window); // true
Object.is({}, {}); // false
const foo = { p: 1 };
const bar = { p: 1 };
const baz = foo;
Object.is(foo, bar); // false
Object.is(foo, baz); // true
Demo:
console.log(Object.is('abc', 'abc'));
console.log(Object.is(window, window));
console.log(Object.is({}, {}));
const foo = { p: 1 };
const bar = { p: 1 };
const baz = foo;
console.log(Object.is(foo, bar));
console.log(Object.is(foo, baz));
Note: This algorithm differs from the Strict Equality Comparison Algorithm in its treatment of signed zeroes and NaNs.
Possible algorithm:
Object.prototype.equals = function(x)
{
var p;
for(p in this) {
if(typeof(x[p])=='undefined') {return false;}
}
for(p in this) {
if (this[p]) {
switch(typeof(this[p])) {
case 'object':
if (!this[p].equals(x[p])) { return false; } break;
case 'function':
if (typeof(x[p])=='undefined' ||
(p != 'equals' && this[p].toString() != x[p].toString()))
return false;
break;
default:
if (this[p] != x[p]) { return false; }
}
} else {
if (x[p])
return false;
}
}
for(p in x) {
if(typeof(this[p])=='undefined') {return false;}
}
return true;
}

Categories

Resources