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.
Related
can someone explain how these two pieces of code achieve the exact same thing* or explain why they may appear to but do not?
for (i = 0; i < xx.length; i++) {
xx[i].classList.remove(...y);
}
xx.forEach(x => {
x.classList.remove(...y);
});
forEach is a method on the Array prototype. It iterates through each element of an array and passes it to a callback function.
So basically, forEach is a shorthand method for the use-case "pass each element of an array to a function". Here is a common example where I think Array.forEach is quite useful, compared to a for loop:
// shortcut for document.querySelectorAll
function $$(expr, con) {
return Array.prototype.slice.call((con || document).querySelectorAll(expr));
}
// hide an element
function hide(el) {
el.style.display = 'none';
}
// hide all divs via forEach
$$('div').forEach(hide);
// hide all divs via for
for (var divs = $$('div'), i = 0; i < divs.length; i++) {
hide(divs[i])
}
As you can see, the readability of the forEach statement is improved compared to a for loop.
On the other hand, a for statement is more flexible: it does not necessarily involve an array. The performance of a normal for loop is slightly better, because there is no function call for each element involved. Despite of this, it is recommended to avoid for loops when it can be written as a forEach statement.
Careful, if you declare "i" without "var" keyword it will be global.
You can check what forEach can do here:
forEach MDN
I've never seen this happen before, and can't find anything about this on the internet. I'm not even really sure how to ask this question.
I can't seem to reproduce this at will, but it is consistent once it starts happening.
When i try to access an element of an array with a variable, such as an iterator, the array is seeing the iterator variable as undefined, because it thinks i'm asking for a member of the array.
so for example:
for(var x = 0; x < width; ++x)
{
if(something != somethingelse)
{
var element = array[x]; // exception
}
}
this for example may cause an exception because x is undefined. So in firefoxes debugger, i check the value of the "x" inside [x], it is undefined. i check the value of "x" in the for loop line, it is a correct integer. So i put a watch on the x inside [x] and find that i'm watching "array.x".
I've been using javascript for years, but i haven't seen this happen before. I don't usually debug with firefox though, so is this an issue with firefox?
i guess my question is, is there anything obvious that i may be doing wrong by accessing an array using a variable?
I forgot to mention, i do have a fix, but it's not something i would like to always do when this happens. right before i access the element inside the array, i set the array member variable to the variable i'm using as an index.
for example:
for(var x = 0; x < width; ++x)
{
if(something != somethingelse)
{
array.x = x;
var element = array[x]; // exception
}
}
Try to type
donald: 'duck'
or even
{donald: 'duck'} // hint: this is considered a scope block instead of an object literal by the console
On the console (I've tested node, chrome, and IE).
I personally got "duck" as output... can someone explain me why?
Outside of object literals, the [identifier]: syntax defines a label. Basically, a label names a specific point of the program. They are a rare feature of JavaScript, but can be used when using break or continue in nested for loops:
outer_loop:
for(var i = 0; i < 10; i++) {
inner_loop:
for(var j = 0; j < 10; j++) {
// will break inner_loop as normal
break;
// will break outer_loop instead
break outer_loop;
}
}
However, if you simply declare a label for some statement, but never use it, it effectively works as if it was never there. Thus the statement
donald: 'duck'
will be the same as just
'duck'
since the label functionality is never used.
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]);
}
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));