Javascript loops and values - javascript

My book says something and I'm not entirely sure what it means. It says that to make sure a loop executes properly, you need to include some code to change the value of the conditional expression?
What does that mean? Is that correct? I may be reading it wrong but when you have a basic Javascript loop like
if(contactsCount > 0) {
for (i = 0; i < contactsCount; i = i + 1){
var item = object[i],
name = item.name,
email = item.email;
target.innerHTML += '<p>' + name + '!</p>;
}
}
})();
Surely you aren't changing any values to make it work? I'm new to this so I'm kind of clueless.

...you need to include some code to change the value of the conditional expression? What does that mean?
That this is a bad idea:
var i = 0;
while (i < 10) {
doSomething(i);
}
Why? Because the loop will never end. i's value is never changed. Endless loops are a classic form of bug.
So what the book is saying is that you must provide for a way for the loop condition (i < 10) to change (e.g., by modifying i's value).
A bit of a tangent, but:
Sometimes you see loops where the condition seemingly can't change, e.g.:
while (true) {
// ...
}
If you find yourself reaching for something like that, stop yourself and try to find a better way. There are very rare use cases for the above, they look like this:
while (true) {
doThis();
doThat();
if (someCondition) {
break;
}
doAnotherThing();
}
...so in that case, the controlling condition is actually in the middle, and the one in the looping statement itself isn't really the condition. This is almost always poor practice, but in very rare situations they can be the right thing to do.
It also says that you can have other statements on the same line as the "if statement", is that right?
Yes, it is. JavaScript doesn't care about lines at all (except when it's doing a form of error-correction for you called Automatic Semicolon Insertion; then lines matter because linebreaks stand in for semicolons as part of the error-correction algorithm). All of these are valid and they all do the same thing:
// 1
if (a < b) {
alert("a is less than b");
foo();
}
// 2
if (a < b) { alert("a is less than b"); foo(); }
// 3
if (a < b)
{
alert("a is less than b");
foo();
}
// 4
if (a < b)
{ alert("a is less than b");
foo; }
Because JavaScript doesn't care about lines at all, they're a matter of style.
By far, the most common style for the above is #1.
Separately, if you have just a single statement in the control-flow statement's body, the block (the {...}) is optional. These do the same thing:
// 1
if (a < b) {
alert("a is less than b");
}
// 2
if (a < b)
alert("a is less than b");
// 3
if (a < b) alert("a is less than b");
So using {...} for a single statement in the body is also, technically, a matter of style. In practice, however, always using blocks leads to fewer bugs in your code. If you leave off the blocks, it will eventually bite you when you add a second statement and forget to add a block:
if (a < b)
alert("a is less than b");
foo();
In the above, foo() is always called, because it's not in the body of the if. That code does this:
if (a < b) {
alert("a is less than b");
}
foo();

In a for loop you should really use the (i++) shorthand but the way your doing it (i=i+1) will work fine as well.
Since I don't have your full source code here is an example...
Here is the JSFiddle demo
//JAVASCRIPT
//animals array
var animals = ['cat','dog','fish','bird','tiger'];
//loop through the animals array
for (i = 0; i < animals.length; i++){
console.log(animals[i]);
}

Related

Function in JavaScript has preceding property? Why?

I have a JS file that i'm working in from a previous employee and there code has functions that look like this:
funcName: function funcName() {
//Some stuff here
}
I've never seen a function start with "funcName:" before.
I removed it and the code still works.
Can someone explain the purpose of putting the function name as a property? (I assume it is a property since it has a leading colon. This function is not wrapped in anything else)
All else being equal, funcName: is a label and is meaningless because it isn't labelling a loop.
For future edification.
Labels can affect the functioning of your code and can be useful. Take a nested loop for example:
primaryLoop:
for (i = 0; i < 3; i++) {
secondaryLoop:
for (x = 0; x < 3; x++) {
if (i === 1 && x === 1) {
break primaryLoop;
}
}
}
We can break out of the primaryLoop by referring to it using the label.
It becomes an anonymous function. before it had the name that you could reference inside itself, after you deleted it the function still exists, just not a named way to reference it.

Why does javascript insist on braces for a function but not for anything else?

In javascript I can have, for example,
var a = 1;
while (a < 10) a++;
if (a === 10) a = 1;
So there are situations where braces are not required (though I usually put them in for clarity and to stop jshint from bothering me about their lack.)
Curiously (to me anyway) function doesn't work the same. I do
function bar(a) { return a + 1; }
but can't do
function foo(a) return bar(a);
What is so different about function that it can't behave like if and while etc?
Eliminating braces for single line statements/expressions is a common pattern across many languages.
It's just syntactic sugar for the (lazy :)) programmer.
If you have multiple statements within the if or while, you would still have to write the {} around them.
I would personally suggest always doing so because forgetting {} could lead to non-obvious bugs sometimes:
let i = 0;
if (i > 0)
i++;
console.log('this still happens');
Addition of arrow functions in ES6 allows this same behavior with functions:
Your function:
function bar(a) { return a + 1; }
Could be written without {} because it has a single expression:
const bar = a => a + 1;
But omitting {} for multiple operations would again be a bug:
let x = x => x + 1; console.log('this still happens');
You could get away with using the , operator to chain expressions:
let i = 0;
if (i > 0)
i++, // <-- notice the comma
console.log('now this does not happen');
But that arguably makes for far less readable code.
Bottom line is, using {} by default is a good choice in most cases.
It's all about syntax.
In scheme, a function maybe looks like this:
(define (square x)
(* x x))
In python, a function maybe looks like this:
def square(x):
return x * x
So, JavaScript Function Declaration Statement is:
function name_this_is_function_header(...parameters) {
// and this is function body
// statements
}
It must include a body which notation is { } . (though, ES6 add a syntax sugar for arrow function, () => { } , you can omit { } if only one statement in it, anyway)
function is a token, ( ) is a pair of tokens, { } also a pair of tokens, compiler or interpreter treat them all as a whole abstraction named JavaScript function.
JavaScript borrowed a lot syntax from Java, Java did the same thing to C++, C++ did the same thing to C ... , that's why.
For statement, such as if and while, it's syntax:
if (condition) one-statement;
while (condition) one-statement;
So, it's all about statement, statement could be single, could be compound.
Single statement don't need { }, compound statement is just several single statements included by { } tokens or notations. If you need several statements after true, you must use compound statement as a whole.
It's not about something mysterious, It's just how do you write it to express.

Undefined Variable thrown

This is a freecodecamp problem where the string argument should be multiplied by the num argument. I understood the other methods they provided, but I'm hung up on how this one works.
repeatStringNumTimes("abc", 3);
//should return "abcabcabc"
I am trying to figure out how the last part of this function (the else statement) inherently knows to multiply the parameters together even though there is no instruction to do so. The way I see it, all it says is: x + (x, y - 1) yet somehow it's still returning correctly.
What am I missing?
function repeatStringNumTimes(str, num) {
if(num < 0)
return "";
if(num === 1)
return str;
else
return str + repeatStringNumTimes(str, num - 1);
}
This is a form of computing called "recursion". It refers to functions that can refer to themselves, thus restarting their cycles until a certain condition is met. In this case, the function is recursively calling itself num times, which in this case yields a simple repetition of its commands.

Using a block's return value in JavaScript

On a lot of browsers I've tested, JavaScript blocks actually return a value. You can test it out in any console:
for(var i = 0; i < 10; i++) {
var sqrt = Math.sqrt(i);
if(Math.floor(sqrt) === sqrt) {
i;
}
}
The "return" value is the last square number, that is, 9! But since it isn't an expression I suppose, you can't do this:
for(var i = 0; i < 10; i++) {
...
} + 5
That doesn't work. It gives + 5, or 5, of course, because it's a separate statement. Putting the loop in parentheses obviously fails, and if a block is in parentheses (e.g. ({f(); r}) - doesn't work) it's treated as an object and throws a syntax error.
One way to take advantage of the return value, as such, is to use eval:
eval('for(var i = 0; i < 10; i++) {var sqrt = Math.sqrt(i);if(Math.floor(sqrt) === sqrt) {i;}}') + 5; // 14
But I'm obviously not going to want to use that if eval is the only solution. Is there a way to use a block's resultant value without using eval that I'm missing? I really like this feature :)
In JavaScript, statements return values of the Completion type (which is not a language type, but a specification type).
The Completion type is used to explain the behaviour of statements
(break, continue, return and throw) that perform nonlocal transfers of
control. Values of the Completion type are triples of the form (type,
value, target), where type is one of normal, break, continue, return,
or throw, value is any ECMAScript language value or empty, and target
is any ECMAScript identifier or empty.
Source: http://es5.github.com/x8.html#x8.9
So, eval() evaluates the program that has been passed in as source text. That program (like any JavaScript program) returns a Completion value. The second item in this Completion value (the "value" item) is returned by the eval() invocation.
So, with eval you are able to retrieve the completion value of an JavaScript program. I am not aware of any other method to accomplish this...
There is a proposal for ES7 to introduce a do expression which allows any block to be turned into an expression. A do expression evaluates a block and returns its completion value.
Using this syntax, which you can try out today with Babel using the syntax-do-expression and transform-do-expression plugins, your example would look like this:
function lastSquareNumber(val) {
return do { for(var i = 0; i < val; i++) {
var sqrt = Math.sqrt(i);
if(Math.floor(sqrt) === sqrt) {
i;
}
}}
}
console.log(lastSquareNumber(10));

Closure Compiler - can a++ >= 3 become ++a > 3?

I admit that I asked a question about why Closure Compiler does not shorten certain code which looks shortenable at first sight a few days ago already, but that reason is not applicable in this case and I'm not really sure why it isn't shortened here.
What code I have is:
var a = 0;
function b() {
return a++ >= 3;
}
Now there is pre-incrementing and post-incrementing. The difference is the return value - a++ returns a and then increments it, ++a first increments a and then returns it.
What this comes down to is that my code could be shortened to (ignoring whitespace removal):
var a = 0;
function b() {
return ++a > 3;
}
However, Closure Compiler does not seem to alter (or recognise) this.
My question therefore is: what side effects could ++a > have when used instead of a++ >=?
There is a particular edge-case for this construct (but not for 3).
It occurs because JavaScript stores numbers as IEEE-754 float-point 64-bit doubles and "only" has a guaranteed "exact" integer-representation up to 2^53 (although implementations may have lee-way to have a higher range, I do not know).
This is on Firefox 4:
a = 2e53
a++ >= 2e53 // true
a = 2e53
++a > 2e53 // false
Real question is what realized gain would such a very particular transformation have? :-0
Happy coding.
It’s safe to apply this size-optimisation if the right-operand (3 in your example) is a constant integer in the range [-252, 252]. In any other case (for example, if the right-operand is fractional or very large), it is not safe.
I would imagine that Closure does not implement this optimisation because:
it requires a lot of checking to ensure that the optimisation is safe,
it only applies in very specific circumstances that probably don’t come up very often, and
It only saves a single character, which hardly seems worth the bother.
Why not check all of the edge conditions yourself?
function b(a) {
return a++ >= 3;
}
function b2(a) {
return ++a > 3;
}
console.log(b(2) === b2(2))
console.log(b(3) === b2(3))
console.log(b(4) === b2(4))
The output is true in each case.

Categories

Resources