I have a json data with specific key as below:
var object = {"85":{"id":"50","nosurat":"2020-PKL-001","user_created":"02211"},"69":{"id":"50","nosurat":"2020-PKL-002","user_created":"02212"},"104":{"id":"50","nosurat":"2020-PKL-003","user_created":"02213"}};
So, in order to iterate it, I use for method.
The problem is how to make filters inside the for method, but only execute it once?
for(var keys in object){
if(object[keys].nosurat == "2020-PKL-001"){
functionx();
}
}
In the above code, the functionx() executed 3 times, because once it's true, it will loop through as many key as my object has. How to make functionx() only executed once in a while, only when the condition is met, assuming that there will be another key that met the condition.
or you could use Array.prototype.some():
var obj = {"85":{"id":"50","nosurat":"2020-PKL-002","user_created":"02211"},"69":{"id":"50","nosurat":"2020-PKL-001","user_created":"02212"},"104":{"id":"50","nosurat":"2020-PKL-001","user_created":"02213"}};
function functionx(o){console.log(o)}
console.log('=== correct behaviour ========================');
Object.values(obj).some(o=>o.nosurat=="2020-PKL-001" && functionx(o) || true);
console.log('=== alternative correct version ==============');
Object.values(obj).some(o=>o.nosurat=="2020-PKL-001" && (functionx(o),true) );
console.log('===== WRONG behaviour (previous version ======');
Object.values(obj).some(o=>o.nosurat=="2020-PKL-001" && functionx(o));
.as-console-wrapper {max-height:100% !important}
Edit:
Oooops, I just corrected a tiny detail: I forgot to mention that in my original solution functionx(o) needed to return some "truthy" value, otherwise multiple calls would still have happened in some()!
I changed the relevant part of the code now to (functionx(o) || true). This will make sure that some() will definitely stop after the first functionx() call (regardless of whatever functionx might return).
One further remark on the && within the function of the .some() loop: the evaluation of boolean expressions follows strict "lazy" rules in JavaScript (as in almost every other language): terms are evaluated from left to right only as far as necessary to get the result of the whole expression. So if the term before the && evaluates as false the overall result of the expression is determined and nothing after the && could change it anymore. Therefore functionx will not be called in these situations and false will be returned to the calling .some() loop.
for(var keys in object){
if(object[keys].nosurat == "2020-PKL-001"){
functionx();
break
}
}
Related
let's say that we have an javascript object like below:
let obj = {name: 'firstName'};
which is a better way to test whether a property exists on an object and is equal to something:
1)
if (obj.address === 'someAddress')
or
2)
if (!!obj.address && obj.address === 'someAddress')
Can someone explain which is better/safer and why?
You asked "safer" and "better". "Better" is subjective as long as you don't define what qualities you're looking for, so I'll ignore that part.
Accessing a property that doesn't exist is valid in JavaScript, and simply returns undefined. So the second way is equivalent to:
const address = obj.address
if (!!address && address === 'someAddress') {
...
}
Now you can see that that's plain silly, because the second condition implies the first. In other words, there is no way that address === 'someAddress' can be true and !!address can be false, so there is no need to do the first check at all.
So the second approach is not safer than the first. Both have the same observable effect.
Nitpicker's corner: if you were checking for some falsy value like 0 or "" instead of the truthy string 'someAddress', then the second approach would not even work, because both conditions can never be true at the same time.
Also, if address is a property with an evil getter that may return a different value each time it's called, all bets are off. The first version could actually be safer because it only gets the value once, but presumably the value would be used inside the if block so the code is still broken.
1 is shorter :D and it works :D
Better is:
if (obj?.address === 'someAddress')
it checks both conditions
In the book 'Functional javascript' by Michael Fogus, I faced with one expression that I still can't undrestand.
Here is the function:
function defaults(d){
return function(o, k){
var val = fnull(_.identity, d[k]);
return o && val(o[k]);
}
}
where
function fnull(fun /*, defaults*/){
var defaults = _.rest(arguments);
return function(/* args */){
var args = _.map(arguments, function(e, i){
return existy(e)?e : defaults[i];
});
return fun.apply(null, args);
};
};
function existy(x){return x != null}
(underscore is the object of Underscore.js library)
and the example of use:
function doSomething(config){
var lookup = defaults({critical:108});
return lookup(config, 'critical');
}
doSomething({critical: 9});
//=> 9
doSomething({});
//=> 108
I've recreated exapmle in node.js and it works fine, but I wonder why is the logical 'and' in the return line of 'default' function?
return o && val(o[k]);
What is the point of doing that? I checked the exapmle with
return val(o[k]);
and it also worked well.
It's hard to believe that this is just a mistake...
The logical and will make sure the second part is only evaluated if the first part is true. If o does not evaluate to true, the expression returns false. Otherwise, it returns val(o[k]).
This is used as a quick check to see if o is not false / null / undefined.
return o && val(o[k])
mean that if "o" is TRUE it will return "val(o[k])"
given "expr1 && expr2":
Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
That is smart usage of something called short "short-circuiting" in logical expressions.
As logical expressions are evaluated left to right, they are tested
for possible "short-circuit" evaluation using the following rules:
false && (anything) is short-circuit evaluated to false.
true ||(anything) is short-circuit evaluated to true.
The rules of logic guarantee that these evaluations are always correct. Note that the (anything) part of the above expressions is not evaluated (meaning not ran at all), so any side effects of doing so do not take effect. There are also benefits to it.
Usage:
Make your expressions evaluate faster by putting something easily calculable or likely to be true/fail at leftmost position in expression.
For example parOfExpressionLikelyToBeTrue && (rest of expression) will in most cases not even calculate the other part of expression. Same goes for parOfExpressionLikelyToBeTrue || (rest of espression).
Same can be used if something is very time consuming to calculate, you push it as far back to the right in expression. For example (rest of the expression) && ThisCostsALotOfTime or (rest of the expression) || ThisCostsALotOfTime. Here when first parts of expression short-circuit you save time on your time consuming part.
Short circuit existence evaluation. Lets say you need to check if your object's property pr is 3? What would you do? obj.pr === 3? Yes and no. What if property is missing? It's fine you will get undefined and that is not === 3. But what if object is not there. You will get trying to read pr of undefined error. You can use short-circuit logic here to you benefit by being defensive and writing the expression as if (obj || obj.pr === 3). This ensures there are no errors, only true and false.
Short circuit initialization. Let's say you wanna say variable a is b. But b might be undefined. And you wanna your variable to have a default. You could write a=b and then check if a is undefined and set it to default or you can be clever and write it as a = b || 3. This way a is b or if be is undefined it's 3. Ofc, you can use this for late initialization as well a = a || 3.
Making sure object for function exists before trying to run function. Same as before mentioned with properties you might wanna test if object containing the function exists before running the function. Let's say you got object obj and function fn as it's property. You might call that function like obj.fn(). It's fine, but if obj is undefined you will get an error. Being defensive you might wanna write: obj && obj.fn().
Running the function only if there is one. Since functions in JS can be passed to other functions you can not be sure at run time it's there. Being defensive you might wanna run your function as (typeof passedFunction === "function" && passedFunction() instead just passedFunction() which my produce an error.
other smart things like guardian expressions etc which are complicated and too many to for me to remember all and you should avoid them anyway for better code readability.
I am relatively new to Javascript and am working through ch. 5 of Eloquent Javascript. I came across some code that I don't quite understand. I know HOW it works (the general method and steps), but I don't understand WHY it works.
The code is here:
function filter(array, test) {
var passed = [];
for (var i = 0; i < array.length; i++) {
if (test(array[i]))
passed.push(array[i]);
}
return passed;
}
Basically the function takes the element the 'for loop is iterating over' from the array, and compares it to the test parameter.
I am wondering how/why this works:
if (test(array[i]))
There is no || && or other 'comparison operators'. How does it compare values with only using parenthesis?
How is test compared to the array[i] value with no operators?
Link to file: http://eloquentjavascript.net/05_higher_order.html
go to 'Filtering an Array' exercise
Thanks!
Whatever is inside the parentheses of an if statement will be evaluated. If the result is falsy (false, 0, "", NaN, null, undefined) it fails and if the result is truthy (everything else) it passes. So if your if statement contains a function call if (test(something)) {}, then the if statement just says if the result of the function call is truthy then pass.
Also, && and || are not comparison operators, they are boolean operators. They just connect the result of two statements, like true || false which evaluates to true.
I am not quite sure, but I think this is a custom function. Most likely there is some comparison there and the result of the function is True/False. If you give us the whole code we could explain it better to you.
This code is accepting a test parameter that is what is called a "predicate function" i.e. a function that given an element will return true or false.
It's going to be used for example with
var big_numbers = filter(numbers, function(x){ return x > 100; });
i.e. the expected parameter test is actually code.
In Javascript passing code is very common and idiomatic. It's something that is more annoying in other languages that don't support the concept of "closure" and of "nested function", forcing all code to live at the top level, being given a name and to have no context (e.g. the C language).
'test' here is a function, not a value. In Javascript, each function is an object and can be passed as parameter. In this case, test is a function that take one parameter and return true or false base on the parameter value.
So in the for loop, test function is called with each array element and if the result is true, it will be store in another array. Eventually, passed elements would be return to the function caller.
Recently I saw a statement that works in javascript on the internet and I wonder what the meaning of a single equal sign (=) in javascript as I mostly use in if statements is.
It is a comparison function which include double equal sign (==)
if(i = 1) {
alert(i);
}
This works, I wondered what would happen when the if statement gets assigned to the value of 1 to the variable i and check the value of i which is the same as:
i = 1
if(i) {
alert(i)
}
But I soon realised that the assignation of a value variable needs to have the keyword var
so I changed the code to:
if(var i = 1) {
alert(i);
}
This time the code doesn't work. Why?
The first part of your analysis is of course correct.
Now, the interesting part might be why your last code if (var ...) { doesn't work.
It doesn't work because
1)
var something
is a statement, not an expression.
2) here's how ECMAScript defines the if statement :
IfStatement :
if ( Expression ) Statement else Statement
if ( Expression ) Statement
You must put an expression in the if clause, not a statement.
More on expressions vs statement in this article.
If you check the console, it says Unexpected token var. You're just not supposed to declare variables in the condition of an if statement.
If you ever do actually mean to make an assignment inside the condition, just declare the variable first, like this:
var i;
if(i = 1){
alert(i);
}
I see that you already know the difference between assignment and comparison, though, which is good :)
Single = is indeed an assignation, if you put it in the if condition it will not compare i against 1 but assign the variable i with the value 1 and then use that value as the condition itself, making i a truthy value. So yes, it is the same as you second example.
Also, in javascript it is better to use === instead of == if you are expecting the items to be the same type :
if (1 == '1') {
alert('this is true'); // where you might actually expect it to be false,
in this case it will work properly if you use triple equals (===).
if (1 === '1') {
alert('this is false'); // which is expected
}
Single = is an assignment operator and will always equate to true in an if statement (assuming it is a non negative value).
Double = ,as in ==, is a comparison and will equate to true only if the values on either side of the operator are equal.
Single "=" means "assign to the left var".
As a return value for the IF, you get the value assigned, and since it is 1, the "true" branch is executed.
However, if you put "var" into the IF, it won't return the assigned value, and I think it won't even work at all.
Mistaking "=" and "==" is a common typo.
Your assertion is correct, in that the code is essentially assigning the value 1 to i and then evaluating the expression's truthiness (1 coeerces to true, so the condition passes).
The last example fails because you can't declare variables inside condition expression.
When you don't explicitly invoke the var keyword, the value will be assigned to any existing variable called i that's available in your scope, or, if none exists, create a property i and assign it to the global object (window), which are all callable without invoking the global object (which is why calling, say location will refer back to window.location — unless you've defined var location in scope).
In this very contrived example, I have an array with 3 elements that I'm looping over using the .each() method.
var vals = $w('foo bar baz');
vals.each( function(val) {
alert(val);
if( val == 'bar' ) {
//This exits function(val)
//but still continues with the .each()
return;
}
});
I can easily return out of the function being called by .each() if I need to.
My question is, how can I break out of the .each() loop from inside the function that .each() is calling?
if( val == 'bar' ) {
throw $break;
}
It's documented at the same page you linked. It's an exception specially handled by the each function. When thrown, it prevents your function from being called on further elements.
Your are correct, and Prototype has created an object ($break) that can be thrown from the each-function to enable this functionality. According to the Prototype API docs:
Regular loops can be short-circuited in JavaScript using the break and continue statements. However, when using iterator functions, your code is outside of the loop scope: the looping code happens behind the scene.
In order to provide you with equivalent (albeit less optimal) functionality, Prototype provides two global exception objects, $break and $continue. Throwing these is equivalent to using the corresponding native statement in a vanilla loop. These exceptions are properly caught internally by the each method.
Also, note that the $continue object has been deprecated, and to simulate a continue-statement, use a vanilla return statement instead.
Code example:
var result = [];
$R(1,10).each(function(n) {
if (0 == n % 2)
return; // this equals continue
if (n > 6)
throw $break;
result.push(n);
});
// result -> [1, 3, 5]
You can read more about the each-function here: http://www.prototypejs.org/api/enumerable/each
Based on the documentation for .each() that you linked to, you should use a throw $break; statement, this should cause further iterations to cease.
Simply returning will cause the iterator to continue to the next one.
From that page you linked to, isn't the correct way
if(val == 'bar')
{
throw $break;
}
?