Why does it work -> key : 'hey' ->'hey' and doesnt throw any error? - javascript

Why does the following code work in javascript ?
key : 'hey'
logs :
'hey'
on the console

Because in that code, key: defines a statement label. The label is followed by an expression statement which is just a string literal. Statements have result values (this is not commonly known) which you cannot directly observe in code, but can in the Read-Evaluate-Print-Loop (REPL) of the browser console, which shows the value resulting from the last statement.
Statement labels are those things you can use to break an outer loop from an inner one:
outer: for (let i = 0; i < 3; ++i) {
for (let j = 0; j < 3; ++j) {
console.log(i, i, i * j);
if (i * j === 2) {
console.log("breaking outer");
break outer;
}
}
}

Related

What the heck operator “:” is for?

If you put on the console smth like a: "Hi" it does not show any error but it prints the value. But when you put a , it says that the variable does not exist. So, why is that? I know colons are used for defining properties inside a json object, but why is that example does not throw an error from the begging.
EDIT : I am looking for the use of colons out of a json object. Not in a switch statement either.
That is a label. They can be used with continue and break when doing nested loops, but i recommend you never use them. Here's an example:
outer:
for (var i = 0; i < 10; i++) {
inner:
for (var j = 0; j < 10; j++) {
console.log(i, j)
if (j == 2) {
break outer;
}
}
}

Javascript: for loop 'for(i=0; i < 3 ; i++)' terminates too early without using continue, break or return

Consider the following piece of code:
function A()
{
for(i = 0; i < 3; i++)
{
console.log("---" + i + "---");
B();
}
}
function B()
{
for(i = 0; i < 3; i++)
{
console.log(i);
}
}
A();
Expected Output:
---0---
0
1
2
---1---
0
1
2
---2---
0
1
2
Received Output:
---0---
0
1
2
I've used a for loop as described here. This is the first result when searching for "javascript for loop" with Google. And dozens of examples are found that suggest a similar approach.
Quote from www.w3schools.com:
for (i = 0; i < cars.length; i++) {
text += cars[i] + "<br>";
}
Why does 'A()' not deliver the expected output?
Note:
I am posting this question because I encountered this problem and didn't find anything on the web about this issue despite that the chance of encountering it is relatively high.
In Javascript variables that are set but weren't declared beforehand
are created in the global scope.
This is fine in most of the cases but since 'i' is often the number one chooses when needing a name for a counter variable this can become a serious issue.
If some for loops are nested of course you would use 'j', 'k', 'l', ... as counter variable names to not interfere with the iterations of other for loops, but when calling a function 'X()' inside a for loop, especially when you aren't the author of 'X()', for loops using the same counter variable names will interfere with each other.
This means you should really declare any counter variable in local scope to avoid such issues, which can be pretty hard to debug if you don't know what you are looking for.
Now let's have a look what happens when calling 'A()' from the question.
function A()
{
for(i = 0; i < 3; i++)
{
console.log("---" + i + "---");
B();
}
}
The following steps are performed before executing 'B()':
The for loop is entered and 'i' is set to '0'.
Since '0 < 3' is true the loop body will be entered.
'---0---' is printed to the console.
Now 'B()' is called.
function B()
{
for(i = 0; i < 3; i++)
{
console.log(i);
}
}
The following steps are performed before 'B()' finishes execution:
The for loop is entered and 'i' is set to '0'.
Since '0 < 3' is true the loop body will be entered.
'0' is printed to the console.
'i' is incremented by '1' and now holds the value '1'.
Now the loop repeats '2. to 4.' but with ever increasing value of 'i': '1' and '2' are printed to the console.
Since '3 < 3' is false the for loop and with it 'B()' finishes execution.
Now we are back in 'A()' but 'i' has a value of '3':
function A()
{
for(i = 0; i < 3; i++)
{
console.log("---" + i + "---");
B();
}
}
Then there are only two additional steps performed:
'i' is incremented by '1' and now holds the value '4'.
Since '4 < 3' is false the for loop and with it 'A()' finishes execution.
So the example from the question should therefore be changed from:
for (i = 0; i < 3; i++) {
//...
}
to
for (var i = 0; i < 3; i++) {
//...
}
or
var i;
for (i = 0; i < 3; i++) {
//...
}

Curly braces in Javascript

I'm currently working through Robin Nixon's Learning PHP, MySQL, Javascript, CSS & HTML5, 4th Edition, and I'm at a part where he explains how to return an array of variables from a function.
The code he used to demonstrate this is:
words = fixNames("the", "DALLAS", "CowBoys")
for(j = 0 ; j < words.length ; ++j)
document.write(words[j] + "<br>")
function fixNames()
{
var s = new Array()
for (j = 0 ; j < fixNames.arguments.length ; ++j)
s[j] = fixNames.arguments[j].charAt(0).toUpperCase() +
fixNames.arguments[j].substr(1).toLowerCase()
return s
}
When I was writing this code, I wrote it:
words = fixNames2("the", "DALLAS", "CowBoys")
for(j = 0; j < words.length; ++j) {
document.write(words[j] + '<br>')
}
function fixNames2() {
var s = new Array()
for(j = 0; j < fixNames2.arguments.length; ++j) {
s[j] = fixNames2.arguments[j].charAt(0).toUpperCase() +
fixNames2.arguments[j].substr(1).toLowerCase()
return s
}
}
I know in an earlier part of the book, he mentions that you don't need to surround single statements with curly braces, and I thought the second for conditional was 2 statements (the s[j] part, and the return s part), so I surrounded the whole thing with curly braces, but for some reason, when written this way, the code only outputs the first word in the array ('the', but correctly formatted by the function so that it's 'The').
I was wondering if anyone could explain to me why this is? Is it that the 2nd for conditional is actually only actually 1 statement? Or does it perhaps have something to do with the way I nested the curly braces?
The "return" is not part of the for loop (it's a part of the function) but you included it within those braces -- so it's not going to work the way the original author intended.
So:
for(j = 0; j < fixNames2.arguments.length; ++j) {
s[j] = fixNames2.arguments[j].charAt(0).toUpperCase() +
fixNames2.arguments[j].substr(1).toLowerCase()
return s //// WRONG
}
Should be:
for(j = 0; j < fixNames2.arguments.length; ++j) {
s[j] = fixNames2.arguments[j].charAt(0).toUpperCase() +
fixNames2.arguments[j].substr(1).toLowerCase()
}
return s;
Or you can even do away with the brackets, since it's just one statement in the for loop:
for(j = 0; j < fixNames2.arguments.length; ++j)
s[j] = fixNames2.arguments[j].charAt(0).toUpperCase() +
fixNames2.arguments[j].substr(1).toLowerCase();
return s;
Note that even though it's on two lines it's considered to be one statement as it should end with a semicolon.
Also,
s =
x
+
y
+
z;
is considered one statement of code. The way to know if something is considered to be a statement is that it's generally ended with a semicolon.
ALWAYS use semicolons to end a statement. It's bad practice not to (even if it runs).

Loop that finds a word in a string

So, i'm working on a 'for' loop that will identify my name, Andrew, and push it into an array, but there's something wrong with it
/*jshint multistr:true */
var text = ("Andrew is really awesome and Andrew should be working on the project, but there is honestly nothing for Andrew to do.");
var myName = ("Andrew");
var hits = [];
for (var i = 0; i < text.length; i ++) {
if (text[i] === "A") {
for (var j = i; i + nyName.length; i ++) {
hits.push(text[j]);
}
}
}
Also, the second loop is supposed to stop when it reaches the end of myName.
You're using JSHINT, so just read the error messages and it'll tell you exactly what's wrong.
Errors:
Line 7: for (var j = i; i + nyName.length; i ++) {
'nyName' is not defined.
Line 3: var myName = ("Andrew");
'myName' is defined but never used.
JSHINT isn't much good if you don't pay attention to what it's telling you.
Also, your inner loop looks odd.
for (var j = i; i + nyName.length; i ++) {
Seems like it'll cause an infinite loop. You're perhaps wanting j with a different condition.
You misspelled myName in your for loop syntax and typed nyName instead, so chances are the script dies as soon as it hits that line.
A typo in the for loop that wants to refer to myName would appear to be a big problem:
for (var j = i; i + nyName.length; i ++)
^
The misspelled myName isn't the only part that fails. You for loop will never end the loop because i + myName.length will always evaluate to true. You also need to increase the value of j or it will always get the character at index i.
Here's the corrected loop.
for (var i = 0; i < text.length; i ++) {
if (text[i] === "A") {
for (var j = 0; j < myName.length; i++, j++) {
hits.push(text[i]);
}
}
}

JavaScript: TypeError with array of functions

So I began to mess around with JavaScript today, and I came across a funny case where it seems convinced that something is a function while also convinced that it's not a function. This code illustrates the issue:
var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
arr1[i] = function(n) { return n + i }
}
var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
arr2[j] = function(n) { return arr1[j](n) }
}
typeof arr2[0] // "function"
arr2[0](2) // TypeError: Property '1' of object [object Array] is not a function
From here, you can assign a variable to arr2[0], and the error persists. I'm not sure if the closures or arrays are necessary to replicate this.
Is there something off with my code, or is this just one of those JavaScript oddities? This isn't something I particularly need an answer to, but it's a little silly so I'd like to know if there's a reason for it.
This actually does have a bit to do with closures.
First, take this code:
for (j = 0; j < arr2.length; j++) {
arr2[j] = function(n) { return arr1[j](n) }
}
The variable j initially holds the value 0, thus arr2[0] is set to a reference to a function.
Next, j is incremented, and now has a value of 1. This terminates the loop.
Now, when the function is called:
return arr1[j](n)
Due to closures, j still has its final value of 1. Which is an invalid index in that array.
One more thing to point out. A for loop doesn't create a new closure, so if you're expecting the anonymous function to enclose the value of j within that iteration, that assumption is wrong. There will be a single instance of j within the entire function that j was declared in.
I think you are trying to make use of closure inside the loop, but it doesn't work like that.
If you want to work with the value of i and j in each step of the loop, you have make make use of an anonymous function as shown below.
var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
arr1[i] = (function(i){
return function(n) {
return n + i
};
})(i);
}
var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
arr2[j] = (function(j){
return function(n) {
return arr1[j](n)
}
})(j);
}
typeof arr2[0]
arr2[0](2)
Demo: Fiddle
It's not doing anything weird.
You're just trying to something that isn't a function (the value of arr1[1], which is undefined).
It's probably safer to initialize arrays in the form:
var arr1 = [];
Or if you're using 'Array' you should initialize it like this:
var arr1 = new Array();

Resources