This question already has answers here:
Why does accessing an element in an object using an array as a key work?
(3 answers)
Closed 6 years ago.
Why does javascript evaluate the following as true, given that object foo has a valid property bar?
foo[[[["bar"]]]] === foo["bar"]
Based on operator precedence, I would think foo[[[["bar"]]]] is trying to access a property with the array [[["bar"]]] as the key, but why does that still "flatten down" to the same as foo["bar"]?
Colleagues of mine are saying javascript parsers have bracket simplifying which ignores the extra brackets. I don't think this is true since saving [[["foo"]]] to a variable test gives the same result:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
What aspect of the language or parser is causing this behavior? Thanks!
JavaScript bracket notation accepts an expression, but it always converts the value of that expression to a string. Thus if you pass in an array, it will attempt to convert it to a string. In your case you are passing in an array [[["bar"]]], and [[["bar"]]].toString() === "bar".
If you are wondering why [[["bar"]]].toString() === "bar", it is because when an array arr is converted to a string implicitly it is like calling arr.join(','). That is each of its elements are converted to strings and then joined in a comma separated string. When the array only has one element, the string representation of the array is just the string representation of that one element. In your case your array ([[["bar"]]]) has one element: [["bar"]].
That array is converted to a string too, and since it is also a one element array, the string representation of it is the string representation of that single element: ["bar"].
["bar"] is also an array with one element, which is a string, so the string representation of ["bar"] is just "bar".
What this comes down to is: [[["bar"]]].toString() === "bar"
and foo[[[["bar"]]]] is the same as foo[[[["bar"]]].toString()].
You would also find that:
foo[[[[1]],[2]]] === foo["1,2"]
because: [[[1]],[2]].toString() === "1,2".
Let's see how foo[[[["bar"]]]] is evaluated, step-by step:
The outermost brackets in foo[...] denote a property
accessor. The expression foo[[[["bar"]]]] thus translates to
accessing a property of foo with name [[["bar"]]].
According to the ECMA standard, the abstract operation
ToPropertyKey(name) is then used to turn the name [[["bar"]]]
into a property key value:
A property key value is either an ECMAScript String value or a Symbol
value.
The name [[["bar"]]] is not of type Symbol and thus converted
into a string. An array is converted to a string by joining all its
string converted values:
[[["bar"]]].toString() === "bar"
Which finally means that our property key actually becomes "bar":
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
Related
This question already has answers here:
Calling member function of number literal
(3 answers)
Closed 3 years ago.
I'm new to Javascript, and I saw code like this:
var myData1 = (5).toString() + String(5);
and the author says he placed the numeric value in parentheses and then called the toString method. This is because you have to allow JavaScript to convert the literal value into a number before you can call the methods that the number type defines.
I'm confused, isn't that 5 is already a number, why 5 needs be converted as (5) to be a number?
The author is partly right. This has nothing todo with turning the literal into a number, this is just about a syntactical distinction: The. can either be used to express fractional numbers (1.1) or it can be used for property access (obj.prop). Now if you'd do:
1.toString()
that would be a syntax error, as the dot is treated as a number seperator. You could do one of the following to use the property access dot instead:
1.0.toString() // as the first dot is the number seperator already, the second dot must be property access
1..toString() // same here
(1).toString() // the dot is clearly not part of the number literal
I want to pass an arithmetic expression as a string to Javascript and this string can contain any number of numerical arrays which will be dynamically populated.
For Eg: I need to evaluate the below expression
(pmPdcpVolDlDrb+pmPdcpVolDlSrb)/8/1024 , Where both pmPdcpVolDlDrb and pmPdcpVolDlSrb are numeric arrays
pmPdcpVolDlDrb =[ Array containing values for sensor pmPdcpVolDlDrb read from storage]
pmPdcpVolDlDrb =[ Array containing values for sensor pmPdcpVolDlDrb read from storage]
This expression can change and the number of variables involved can also change. I need a generalized way of handling it. I wrote the below code and it serves my purpose. I need to know if there is a better and standard way for the same.
// Expression for evaluation where pmPdcpVolDlDrb and pmPdcpVolDlSrb are arrays
expression="(pmPdcpVolDlDrb+pmPdcpVolDlSrb)/8/1024"
// Seperating out the variables from the expression. In my case variable names always start with pm
variables=expression.split(/\W+/).filter(word => word.includes("pm"));
array=[]
for(i=0;i<variables.length;i++){
array[i]= [1,2,3,4]// Replace with actual code to get the values of arrays to be computed
if (i===0)
expression=expression.replace(variables[i],"a")
else
expression=expression.replace(variables[i],"array["+i+"][i]")
}
resultantArray=array[0].map((a, i) => eval(expression))
This question already has answers here:
What is the difference between string primitives and String objects in JavaScript?
(12 answers)
Closed 4 years ago.
I’m studying JavaScript and this is a statement I came across:
new String("Hello");
This will create a new string that is the same as string literal "hello", although it will be classed as an object rather than a primitive values. For this reason it is preferable to use the string literal notation.
What is a String literal?
Why is new String("Hello") classed as Object?
A literal string (or literal <any data type>) means that you just reference the data directly.
For example
"Hello".length // returns 5
The "Hello" is a string literal since we are just referencing it "as-is".
You could do exactly the same thing with a string object:
var strObj = new String("Hello");
strObj.length // returns 5
These two examples are pretty much identical (for the sake of this example). Both create a string variable and measure it's length.
The first uses a string literal and the second uses a string object.
Here is another example using numbers - if you do a direct calculation such as:
5 + 2
you'll be using number literals - again, when you only reference the data directly, it is considered a "literal".
I am trying to get the content of a data attribute with jquery but returned data is not what I had set.
With this simple example:
<div id="test" data-test="[1]"></div>
But $('#test').data('test') returns 1 instead of [1]
No problem using pure javascript.
View it online: https://jsfiddle.net/jojhm2nd/
jQuery's data is not an attribute accessor function. (This is a common mistake, easily made.) To just access the attribute, use attr.
$("#test").attr("data-test");
data does read data-* attributes, but only to initialize jQuery's data cache for that element. (And it never writes attributes.) It does a whole series of things including changing names (data-testing-one-two-three becomes testingOneTwoThree, for instance) and interpreting the values. In this case, it interprets the value as an array because it starts with [. When you show that array with alert, it's coerced to a string, and when you coerce an array to a string, that does an Array#join. If your attribute had been [1, 2], for instance, you'd've seen 1,2 as the result.
From the docs linked above:
Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). A value is only converted to a number if doing so doesn't change the value's representation. For example, "1E02" and "100.000" are equivalent as numbers (numeric value 100) but converting them would alter their representation so they are left as strings. The string value "100" is converted to the number 100.
When the data attribute is an object (starts with '{') or array (starts with '[') then jQuery.parseJSON is used to parse the string; it must follow valid JSON syntax including quoted property names. If the value isn't parseable as a JavaScript value, it is left as a string.
jQuery does magic when you use the .data method.
From the jQuery website:
Every attempt is made to convert the string to a JavaScript value
(this includes booleans, numbers, objects, arrays, and null).
You can use the .attr method and do:
$('#test').attr('data-test');
In JavaScript, typeof 0 gives 'number' not 'Number', but instanceof 0 Number.
Would it be accurate to say the canonical names of the built-in types are capitalized, and the lowercase return value of typeof is a quirk/inconsistency that can't be changed for historical reasons, but would be changed if it could be? Or am I missing something?
No,
Actually number is the built-in value type where Number is an object.
If you say typeof there's no need to temporarily convert 0 to an Object.
If you use instanceof, it temporarily converts 0 to an object.
This is similar to what you do with a string:
"sometest" => This is a string
However, if you would do "sometest".toLowerCase() it will first (temporarily) convert the string to a String-object and then call the method on that object (since value-types can't have methods).
In short, lowercase means value-type, uppercase means object