javascript if (a.b.v.c.d.e === true) [duplicate] - javascript

This question already has answers here:
Test for existence of nested JavaScript object key
(64 answers)
Closed 6 years ago.
What's an easy way to check
if (a.b.v.c.d.e === true) {}
and return false if any of b or c or v is undefined?
Coffeescript handles it easily but what is a comparable solution in vanilla javascript? Is there a library that has this common issue taken cared of?

Javascript does not have a pretty feature to do this (without using any helper functions). You can use && operator to do this:
if (a && a.b && a.b.v && a.b.v.c && a.b.v.c.d && a.b.v.c.d.e === true) {}

You can use the short-circuiting behavior of && to express the chained dependencies.
if (a && a.b && a.b.v && a.b.v.c && a.b.v.c.d && a.b.v.c.d.e === true)

Write a function and call it like this:
if (ignoreNulls(a, 'b', 'v', 'c', 'd', 'e') == true) {
// ...
}
function ignoreNulls() {
var args = Array.prototype.slice.call(arguments);
var subj = args.shift();
while (prop = args.shift()) {
var v = subj[prop];
if (v !== null && v != undefined) {
subj = v
} else {
return null;
}
}
return subj;
}

Related

I failed Javascript tech interview but I dont know why

I was only allowed to use google document for writing.
Could you please tell me what I did wrong? The recruiter wont get back to me when I asked her why I failed
Task 1:
Implement function verify(text) which verifies whether parentheses within text are
correctly nested. You need to consider three kinds: (), [], <> and only these kinds.
My Answer:
const verify = (text) => {
   const parenthesesStack = []; 
   
  for( let i = 0; i<text.length; i++ ) {
const closingParentheses = parenthesesStack[parenthesesStack.length - 1]
if(text[i] === “(”  || text[i] === “[” || text[i] === “<”  ) {
parenthesisStack.push(text[i]);
} else if ((closingParentheses === “(” && text[i] === “)”) || (closingParentheses === “[” && text[i] === “]”) || (closingParentheses === “<” && text[i] === “>”) ) {
   parenthesisStack.pop();
} 
  };
return parenthesesStack.length ? 0 : 1;  
}
Task 2:
Simplify the implementation below as much as you can.
Even better if you can also improve performance as part of the simplification!
FYI: This code is over 35 lines and over 300 tokens, but it can be written in
5 lines and in less than 60 tokens.
Function on the next page.
// ‘a’ and ‘b’ are single character strings
function func2(s, a, b) {
var match_empty=/^$/ ;
if (s.match(match_empty)) {
return -1;
}
var i=s.length-1;
var aIndex=-1;
var bIndex=-1;
while ((aIndex==-1) && (bIndex==-1) && (i>=0)) {
if (s.substring(i, i+1) == a)
aIndex=i;
if (s.substring(i, i+1) == b)
bIndex=i;
i--;
}
if (aIndex != -1) {
if (bIndex == -1)
return aIndex;
return Math.max(aIndex, bIndex);
} else {
if (bIndex != -1)
return bIndex;
return -1;
}
};
My Answer:
const funcSimplified = (s,a,b) => {
if(s.match(/^$/)) {
return -1;
} else {
return Math.max(s.indexOf(a),s.indexOf(b))
}
}
For starters, I'd be clear about exactly what the recruiter asked. Bold and bullet point it and be explicit.
Secondly, I would have failed you from your first 'for' statement.
See my notes:
// Bonus - add jsdoc description, example, expected variables for added intention.
const verify = (text) => {
// verify what? be specific.
const parenthesesStack = [];
for( let i = 0; i<text.length; i++ ) {
// this could have been a map method or reduce method depending on what you were getting out of it. Rarely is a for loop like this used now unless you need to break out of it for performance reasons.
const closingParentheses = parenthesesStack[parenthesesStack.length - 1]
// parenthesesStack.length - 1 === -1.
// parenthesesStack[-1] = undefined
if(text[i] === “(” || text[i] === “[” || text[i] === “<” ) {
parenthesisStack.push(text[i]);
// “ will break. Use "
// would have been more performant and maintainable to create a variable like this:
// const textOutput = text[i]
// if (textOutput === "(" || textOutput === "[" || textOutput === "<") {
parenthesisStack.push(textOutput)
} else if ((closingParentheses === “(” && text[i] === “)”) || (closingParentheses === “[” && text[i] === “]”) || (closingParentheses === “<” && text[i] === “>”) ) {
parenthesisStack.pop();
// There is nothing in parenthesisStack to pop
}
};
return parenthesesStack.length ? 0 : 1;
// Will always be 0.
}
Not exactly what the intention of your function or logic is doing, but It would fail based on what I can see.
Test it in a browser or use typescript playground. You can write javascript in there too.
Hard to tell without the recruiter feedback. But i can tell that you missundertood the second function.
func2("mystrs", 's', 'm') // returns 5
funcSimplified("mystrs", 's', 'm') // returns 3
You are returning Math.max(s.indexOf(a),s.indexOf(b)) instead of Math.max(s.lastIndexOf(a), s.lastIndexOf(b))
The original code start at i=len(str) - 1 and decrease up to 0. They are reading the string backward.
A possible implementation could have been
const lastOccurenceOf = (s,a,b) => {
// Check for falsyness (undefined, null, or empty string)
if (!s) return -1;
// ensure -1 value if search term is empty
const lastIndexOfA = a ? s.lastIndexOf(a) : -1
const lastIndexOfB = b ? s.lastIndexOf(b) : -1
return Math.max(lastIndexOfA, lastIndexOfB)
}
or a more concise example, which is arguably worse (because less readable)
const lastOccurenceOf = (s,a,b) => {
const safeStr = s || '';
return Math.max(safeStr.lastIndexOf(a || undefined), safeStr.lastIndexOf(b || undefined))
}
I'm using a || undefined to force a to be undefined if it is an empty string, because:
"canal".lastIndexOf("") = 5
"canal".lastIndexOf(undefined) = -1
original function would have returned -1 if case of an empty a or b
Also, have you ask if you were allowed to use ES6+ syntax ? You've been given a vanilla JS and you implemented the equivalent using ES6+. Some recruiters have vicious POV.

How does instanceof operator actually work in JS? [duplicate]

This question already has answers here:
Why is 4 not an instance of Number?
(5 answers)
Closed 8 months ago.
I've searched the site for this question and got the following answer:
function instance_of(V, F) {
var O = F.prototype;
V = V.__proto__;
while (true) {
if (V === null)
return false;
if (O === V)
return true;
V = V.__proto__;
}
}
It's from https://stackoverflow.com/a/9220317/12974414.
But I tested the following code, found something weird:
console.log( (10).__proto__ === Number.prototype ) // true
console.log( instance_of(10, Number ) ) // true
console.log( 10 instanceof Number ) // false
function instance_of(V, F) {
var O = F.prototype;
V = V.__proto__;
while (true) {
if (V === null)
return false;
if (O === V)
return true;
V = V.__proto__;
}
}
How to explain this and how does instanceof operator actually work in JS ?
JavaScript has a feature called autoboxing which converts primitives to Objects when you try to access properties on them.
instanceof doesn't autobox and a primitive number is not an instance of the Number class.
You can see, in the specification:
If Type(O) is not Object, return false.

Pattern matching expressions in Javascript

Im making my way throught functional programming in JS. Recently I started to use Daggy to accomplish simple pattern matching, but I don't think that I fully get it.
Given this code:
if(a === 1 && !b) {
do(y)
}
if(b === 3 && c === 2) {
do(z)
}
if (a) {
do(x)
}
Is there a way to improve this cohercions into something similar to?:
when [a === 1 && !b] : do(y)
when [a] : do(x)
when [b === 3 && c === 2]: do(z)
JavaScript doesn't have the kind of pattern matching you're probably talking about. There is an active proposal to add it using case/when, here's an example from that proposal:
const res = await fetch(jsonService)
case (res) {
when {status: 200, headers: {'Content-Length': s}} -> {
console.log(`size is ${s}`)
}
when {status: 404} -> {
console.log('JSON not found')
}
when {status} if (status >= 400) -> {
throw new RequestError(res)
}
}
It's currently just at Stage 1 of the process, though, so it may not proceed, may change radically before proceeding, and may take years to work through the stages and get into the language. There's work on a Babel plugin.
I'm afraid it's not immediately clear to me how I'd apply it to your example, though, as it seems to want an operand for case.
In the meantime, a series of if/else if can be fairly terse if terseness is what you're looking for:
if (a === 1 && !b) foo(y);
else if (a) foo(x);
else if (b === 3 && c === 2) foo(z);
Or JavaScript's switch is unusually flexible (it's really just another way to write if/else if):
switch (true) {
case a === 1 && !b: foo(y); break;
case a: foo(x); break;
case b === 3 && c === 2: foo(z); break;
}
(I'm not advocating it, just pointing out it's an option.)
You can create a wrapper class to your data and then use functions to check the conditions and do an action in case that the particular condition meets.
Simple and easy, without any libraries.
class typeWrap {
constructor(obj) {
this.var = obj;
this.done = false;
}
when (condition, doFn) {
if (!this.done && condition(this.var)) {
this.done = true;
doFn(this.var);
}
return this;
}
}
const data = new typeWrap({
b: 3, c : 9
});
data
.when(
d => d.a === 1 && !d.b,
() => console.log('C1 => y')
)
.when(
d => d.b === 3 && d.c !== 2,
() => console.log('C2 => z')
)
.when(
d => d.a,
() => console.log('C3 => x')
)
.when(
d => true,
() => console.log('Last stop')
);
Sure with Daggy you could define Maybe
const Maybe = daggy.taggedSum('Option', {
Just: ['a'],
Nothing: []
})
and then define a prototype function on it called alt which can basically fallback to the passed value
// alt :: Alt f => f a ~> f a -> f a
Maybe.prototype.alt = function(o): Maybe<T> {
return this.cata({
Just: _ => this,
Nothing: () => o
})
}
So with it we can do some pattern matching or similar
function match(comparator, res) {
switch (comparator()) {
case true: return Maybe.of(res)
case false: return Maybe.Nothing
default: return Maybe.Nothing
}
}
MaybeF.Nothing
.alt(match(() => a === 1 && !b, () => y))
.alt(match(() => a, () => x))
.alt(match(() => b === 3 && c === 2, () => z))
Developer and maintainer of Patroon. I was looking for js style pattern matching and had to build my own. This is what your example would look like using the patroon library:
const isNil = x => !(x != null)
patroon(
{a: 1, b: isNil}, y,
{b: 3, c: 2}, z,
{a: _}, x
)({a, b, c})
https://github.com/bas080/patroon

Javascript Empty String vs (null and undefined) [duplicate]

This question already has answers here:
How can I check for "undefined" in JavaScript? [duplicate]
(16 answers)
Closed 6 years ago.
I have a object
var data = {1:undefined,2:null,3:10,4:""}
I want to replace all the undefined and null values by 0. I am using the following code to do that:
for (var index in data) {
if (!data[index]) {
data[index] = 0;
}
}
Result I am expecting is : {1:0,2:0,3:10:4:""}
But Result is : {1:0,2:0,3:10:4:0} because it is considering empty string as null. Is it known behavior ?
I can check it by using
(if(data[index] == undefined || data[index] == null))
But I wanted to know the behavior of the above solution.
You can add typeof data[index] != 'string'
var data = {1:undefined,2:null,3:10,4:""}
for (var index in data) {
if (!data[index] && typeof data[index] != 'string') {
data[index] = 0;
}
}
console.log(data)
This is because a string of length 0 is "falsy", which means that it, if evaluated as a boolean, will translate to false. Read more on "falsy" over here. You can fix your code in the following way:
for (var index in data) {
if (typeof data[index] == "undefined" || data[index] == null) {
data[index] = 0;
}
}
Try:
if ((typeof <your variable> == "undefined") ||
( <your variable> == "" ) ) {
<your variable> = 0 ;
}
By the way, Are you using "1", "2" indices?

How can I test two strings for equivalence in JavaScript, considering null and empty string the same?

If I compare "a" and "b", that should be false.
If I compare "a" and "a", that should be true.
If I compare "" and null, that should be true.
I could write my own method, but thought there was perhaps a JavaScript shortcut.
Edit: I was thinking something like this:
areDbSame(s1, s2) {
if (s1 === null) s1 = "";
if (s2 === null) s2 = "";
return s1 === s2;
}
Edit2: Settled on this version:
areDbSame(s1, s2) {
return (s1 === null ? "" : s1) === (s2 === null ? "" : s2);
}
Just before you test the equality of your string, you could do a simple one line enforcement, by converting to '' in the case of null. For example (if you also don't care about undefined, false, etc):
// testString becomes the one you are testing
var testString = myString || '';
If you only want to ensure null is blank
var testString = (myString === null) ? '' : myString;
Then you can simply do your string comparisons using testString, and not worry about the null equalities.
IMO this is the cleanest answer because it doesn't convolute the original equality testing of javascript strings. It is the same as saying, let's split the problem up into two parts.
1) When should my string be considered blank, and
2) Now I can just check for regular string equality.
function areEqualStrings(a, b) {
var otherEqualValues = ['', null];
if(typeof a === 'string' && typeof b === 'string') {
return a === b;
} else if(otherEqualValues.indexOf(a) > -1 && otherEqualValues.indexOf(b) > -1) {
return !a === !b;
} else {
return false;
}
}
When coercing JavaScript values, !null is true and !'' is true, so those would result in being equal.
Here's the test (screenshotted from my console):
This function should do it. It type checks first and short circuits otherwise.
function stringCompare(a, b) {
if (((a === null || typeof a === 'string') ||
(b === null || typeof b === 'string')) &&
((a === '' && b === null) ||
(b === '' && a === null) ||
(a === b))) {
return true;
}
return false;
}
No it hasn`t. The two first cases you can do naturally using operator =.
The third case it is impossible because "" is considered a empty string and null has any type. So they never can be true naturally. To do this, you have to write your own method.
Just to be clear. You can use operators = (equal) to do comparison:
== equal to
`x == 8 false
x == 5 true
x == "5" true
=== equal value and equal type
x === 5 true
x === "5" false
Hope it helps

Categories