The following code snippet assigns some values by mixing parentheses and square brackets without any error, however most of the other combinations (e.g. parentheses inside square brackets) don't work at all.
var myItems = [];
myItems[5] = ("A1", "B1", ["C1","C2","C3"]);
When I print the values, they are exactly the same in two different browsers.
myItems[5]: C1,C2,C3
myItems[5][0]: C1
myItems[5][1]: C2
myItems[5][2]: C3
myItems[5][2][0]: C
myItems[5][2][1]: 3
myItems[5][2][2]: undefined
It seems that only the part inside square brackets is considered. Is this outcome defined by the JavaScript standard (ECMA-262)? Or is it just what the interpreter/engine (Chrome and Firefox in my case) did in the face of an illegal use?
var myItems = [];
//myItems[5] = ["A1", "B1", ["C1","C2","C3"]];
myItems[5] = ("A1", "B1", ["C1","C2","C3"]);
document.getElementById("demo").innerHTML =
"myItems[5]: " + myItems[5] + "<br/>" +
"myItems[5][0]: " + myItems[5][0] + "<br/>" +
"myItems[5][1]: " + myItems[5][1] + "<br/>" +
"myItems[5][2]: " + myItems[5][2] + "<br/>" +
"myItems[5][2][0]: " + myItems[5][2][0] + "<br/>" +
"myItems[5][2][1]: " + myItems[5][2][1] + "<br/>" +
"myItems[5][2][2]: " + myItems[5][2][2] + "<br/>" +
"";
<p id="demo"></p>
EDIT: I know the correct use of brackets (my fiddle already had it), but I'm asking if the outcome is deterministic at such a wrong use. Since the interpreters I've tried don't produce any error and give the same results, I want to know if these results are ensured by the standard and/or all the other interpreters will do the same.
From MDN on comma operator
The comma operator evaluates each of its operands (from left to right)
and returns the value of the last operand.
So
myItems[5] = ("A1", "B1", ["C1","C2","C3"]);
Turns to
myItems[5] = (["C1","C2","C3"]);
Now you've got yourself an array with 6 elements (5x undefined and the array of three strings you assigned at sixth position).
And it is exactly what you're getting printed out.
The comma operator , "evaluates each of its operands (from left to right) and returns the value of the last operand." (You can take that quote from Mozilla as gospel, or try to decipher what ECMA has to say on the matter.)
The grouping operator ( ) "controls the precedence of evaluation in expressions," according to Mozilla. (Obligatory link to ECMA.)
In this instance, the grouping operator does essentially nothing, since there is only one expression being grouped. So this is a simple comma-separated list of values, the last one of which is an array. This is what gets assigned.
The comma operator is often seen when assigning variables in bulk, e.g. var foo = 1, bar = 2, baz = 3; The spec states that even though only the last item is returned, each item must be evaluated "because it may have observable
side‑effects." In this most common of use cases, the variables each have values assigned to them.
Related
it("should know properties that are functions act like methods", function() {
var meglomaniac = {
mastermind : "Brain",
henchman: "Pinky",
battleCry: function(noOfBrains) {
return "They are " + this.henchman + " and the" +
Array(noOfBrains + 1).join(" " + this.mastermind);
}
};
var battleCry = meglomaniac.battleCry(4);
expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
});
What is the definition of Array in this code (line 7)? I looked it up and it looks like it's an Array.of() command which generates an empty array of length n which in this case would be 5? So why does it end up with only 4 brain inputs assuming that is the correct assumption? Or is this array() doing something else?
battleCry(4) means that Array(noOfBrains + 1) will indeed have a length of 5:
[empty, empty empty, empty, empty]
But when you .join those 5 elements, you only insert something into the spaces between them, and there are only 4 spaces:
[empty, empty empty, empty, empty]
// ^ ^ ^ ^
So, you end up with 4 occurrences of this.mastermind in the resulting string.
This code is quite confusing. I'd strongly prefer something like .repeat instead:
var meglomaniac = {
mastermind : " Brain",
henchman: "Pinky",
battleCry: function(noOfBrains) {
return `They are ${this.henchman} and the${this.mastermind.repeat(noOfBrains)}`
}
};
var battleCry = meglomaniac.battleCry(4);
console.log(battleCry === 'They are Pinky and the Brain Brain Brain Brain');
Array is just the array constructor. It's not really anything special, it just creates an array which has a length of the parameter (when passed a number).
You can avoid having to manually add 1 to the number of elements in the Array to overcome the problem, by using Array.fill().
Array(4).fill("Brain").join(" "); // have an array of 4 elements,
// fill each vacant spot with "Brain"
// and flatten it by separating elements
// by a space
//Brain Brain Brain Brain
So your code can be simplified as:
Array(noOfBrains).fill(this.mastermind).join(" ");
When the statement console.log(1 + + " " + 3); is executed in the Chrome console, the result is 4 and not "1 3" as i would expect.
Can someone please explain why this is the case?
This behaviour is called coercion.
In this case the unary plus operator + converts to number the expression at the right. If it cannot parse a particular value, it will evaluate to NaN.
+ " " //--> is coerced to 0
You can see some coercion examples in this Gist:
JavaScript Coercion
If you simply broke down the problem into its constituent parts and typed +" " into the console, you'd see that it evaluates to 0. And 1+3+0 is 4.
The following operations are done when the statement is evaluated:
1 // one
+ // add
+ " " // implicitly convert " " to a number (0)
+ // add
3 // three
So basically 1 + 0 + 3. There’s no string that enters this calculation. It’s converted to a number beforehand.
The + operator in this case is the unary + (see “coercion”).
Please look at the following code. I can't get my values to add up. The digit just adds itself to the back of the string. Wonder any way to go about it.
$("a[name='older_post']").click(function(){
$("div.main_ads_div a[name='older_post']").remove().fadeOut();
var last_td_id=parseInt($("table.main_ads_table:last").find("td.load_ads:last").attr("id"),10);
alert(last_td_id); //OUTPUTS 38
$("div.main_ads_div").append('<table class="main_ads_table" col="7" row="7"><tr><td class="load_ads" id="'+last_td_id+1+'"></td><td class="load_ads" id="'+last_td_id+2+'"></td><td class="load_ads" id="'+last_td_id+3+'"></td><td class="load_ads priority" id="'+last_td_id+4+'"></td><td class="load_ads priority" id="'+last_td_id+5+'"></td><td class="load_ads" id="'+last_td_id+6+'"></td><td class="load_ads" id="'+last_td_id+7+'"></td><td class="load_ads" id="'+last_td_id+8+'"></td></tr></table>');
});
So what I'm trying to get here is for the each td that appends, I'm trying to get 39, 40, 41, 42... But I'm getting values such as 381, 382, 383,... etc etc.
Any help here appreciated.
Wrap the addition in parentheses:
... + (last_td_id + 7) + ...
You are concating string with number, enclose the addition in parentheses to perform arithmatic operation on it.
Change
+last_td_id+1+
To
+(last_td_id+1)+
The association of + is left to right and in the statement '....class="load_ads" id="'+last_td_id first concatenates the left hand string with number (last_td_id) and gives a string which again concatenates the incremental number like (2 or 3 ..) to previous string. Putting the parenthesis around the number makes its precedence high and the calucation is performed first and result is concatenated in the string.
The plus operator only performs mathematical addition only if both operands are numbers. If one of them is a string, it will perform string concatenation (and cast the 1 to "1").
Yet it is left associative, and you are not using parenthesis. So your expression is evaluated as
(((…('<…' + id) + 1) + '"…') + id) + 2) + …
and every single step yields a string. You will need to enforce the addition to be executed first by wrapping it in parenthesis, as others have already mentioned:
'<…' + (id + 1) + '"…' + (id + 2) + …
// evaluated as
(((…('<…' + (id + 1)) + '"…') + (id + 2)) + …
Using '+' in javascript always appends the variables/strings. Try something like this:
var c = (16 * 24) + 12;
d = c.toString();
Only then the var 'd' will give you the mathematical output
In your case, it could be
(last_td_id+4).toString(); and so on
While I do know that the following question is stupid simple, it is related to a specific situation that I have been unable to find through Google. The following code is in Javascript.
Suppose there is a variable
x = x + 1;
I can see from a tutorial that this is supposed to work. However, how are we supposed to use this variable in a calculation?
I have tried with the following codes
var name = name + 1;
alert(name);
The above outputs "NaN"; whatever that is...
var name = name + 1;
name = 2;
alert(name);
The above outputs 2 which is simply overriding the original variable.
name = prompt("input any number");
var name = name + 1
alert(name);
The above outputs the input provided + 1 as a string, i.e. 01 where the input is "0" without quotes.
I remember from a ruby lesson that we use .to_i in order to convert a string to an integer. How do we go about doing this in Javascript?
var name = name + 1;
The above code declares a new variable called name which contains whatever name contained before, plus 1. Since name only just came into existence, it doesn't have a numeric value ("Not A Number", or NaN). Adding 1 to NaN gives NaN.
+ means different things in different contexts. If the two operands are numbers, then it does addition. If one operand is a String, it does String concatenation, so
var x = "2"; // x is the String "2"
alert(x+2); // "22"
var x = 2; // x is the number 2
alert(x+2); // 4
If you want to convert a String to a number, you can do
if (x) x = parseInt(x, 10);
where the second argument is the radix (i.e. the base of the number system), and you should use it. If someone entered 02 for example, the radix prevents javascript from treating that as an octal (or other) number.
Of course, you always need to make sure your variables are defined before you use them. I bet your NaN result is coming from the variable not being defined.
Your issue is that you never initialize name. For example:
var name = 0;
alert(name); // Name is 0
name = name + 1;
alert(name); // Name is 1
If you don't initialize it, it will give you NaN: Not a Number.
To turn a string into a number, use parseInt or parseFloat:
var name = prompt("input any number"); // I input 3
name = parseFloat(name);
name = name + 1;
alert(name); // Name is 4
Use parseInt to convert a string to a number.
The line x = x + 1 says "take the existing value of x, add one to it, and store the resulting value back in x again".
The line var name = name + 1 is meaningless since name does not have an existing value when the statement is executed. It is the same as saying undefined + 1 which is NaN (Not a Number).
Here are some examples of how the + operator works in JavaScript:
1 + 2 // number + number is a number -> 3
"1" + 2 // string + anything is a string => "12"
1 + "2" // anything + string is a string => "12"
"1" + "2" // string + string is a string => "12"
NaN means "not a number". Since name has no value when it is first declared, saying "var name = name + 1" doesn't have a numerical meaning, since name is in the process of being declared when used for the first time.
In the second example, name is determined to be a string. Javascript isn't as sensitive to types as some other languages, so it uses + as a concatenation operator instead of a numerical one, since it makes more sense in context,
This is all in the context of a larger program, so Im going to try keep it simple, showing the offending lines only. I have an array of values that are numbers in string form a la "84", "32", etc.
Yet THIS line
console.log(unsolved.length + " " + unsolved[0] + " " + parseInt(unsolved[0]) + " " + parseInt("84"));
prints:
4 "84" NaN 84
"84" is the array element Im trying to parseInt! Yet it won't work unless I take it out of the context of an array and have it explicitly written. What's going on?
You can try removing the quotations from the string to be processed using this function:
function stripAlphaChars(source) {
var out = source.replace(/[^0-9]/g, '');
return out;
}
Also you should explicitly specify that you want to parse a base 10 number:
parseInt(unsolved[0], 10);
parseInt would take everything from the start of its argument that looks like a number, and disregard the rest. In your case, the argument you're calling it with starts with ", so nothing looks like a number, and it tries to cast an empty string, which is really not a number.
You should make sure that the array element is indeed a string which is possible to parse to a number. Your array element doesn't contain the value '84', but actually the value '"84"' (a string containing a number encapsulated by ")
You'll want to remove the " from your array elements, possible like this:
function removeQuotationMarks(string) {
return (typeof string === 'string') ? string.replace(/"|'/g, '') : string;
}
unsolved = unsolved.map(removeQuotationMarks);
Now all the array elements should be ready to be parsed with parseInt(unsolved[x], 10)
First we need to replace " to ' in give data using Regex and replace and then we need to cast.
var i = 1;
var j = "22"
function stringToNumber(n) {
return (typeof n === 'string') ? parseInt(Number(n.replace(/"|'/g, ''))) : n;
}
console.log(stringToNumber(i)); // 1
console.log(stringToNumber(j)); // 22