Unintentionally, In my project I had used the following code and I was surprised to see that is working:
HTML
<span id="output"></span>
Javascript
var myObject = {
'a': '----First---',
'b': '----Second---',
'c': '----Third----'
};
var myArray = ['a'];
// First Case
output.innerHTML = myObject[myArray];
var myArray2 = ['b'];
// Second Case
output.innerHTML += myObject[myArray2];
var myArray3 = ['a', 'b'];
// Third Case
output.innerHTML += myObject[myArray3];
Output
----First-------Second---undefined
Jsbin Link: http://jsbin.com/godilosifu/1/edit?html,js,output
I am directly accessing array reference within Object which should be undefined in all the cases but strangely When array is of Size 1, it always gets the first element and use that as the object key.
I just want to know what is this concept called and why is this happening ?
Because the property name has to be a string, it is type cast into one using the toString() method. The reason that your third example is undefined is that ['a', 'b'].toString() equals 'a,b', which is not a property in your object.
Property names
Property names must be strings. This means that non-string objects
cannot be used as keys in the object. Any non-string object, including
a number, is typecasted into a string via the toString method.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors
Worth noting is that in ECMAScript 6, there is a new collection type called Map, which allows you to use any object as a key without type coercion.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
When you pass the array to the object as a Key, it is calling toString() on it. This is because all Keys in Javascript are Strings.
['a'].toString() is "a"
myObject['a'] is "----First----"
See: Keys in Javascript objects can only be strings?
It's auto-casting. In Javascript, only strings can be indexes into an object's properties. myObject is not an array, it's an object. Even though you're using the brackets to access it's properties, it is not the same meaning as brackets used on an array object.
Due to object properties only being allowed to be named by strings, the compiler auto-casts your array to a string (essentially calling it's native toString() function, which for an array, joins all the elements with a comma).
So when you pass your array to the object's property accessor/index, it does this:
myArray1 ==> "a";
myArray2 ==> "b";
myArray3 ==> "a" + "," + "b" ===> "a,b";
Related
I am getting confused on how this snippet of code works. I would assume that the A would need to be 'A' in order for these two characters to swap, but it works. Also, is there a name for what this is doing? From the looks of it, I think it is destructuring, but I'm not certain.
var translations = {
A : 'U'
};
console.log(translations['A']); //returns U
I would have assumed you need to write it this way:
var translations = {
'A' : 'U'
};
console.log(translations['A']); //also returns U
https://jsfiddle.net/ud37asp8/14/
Object or property keys can be either an identifier name (i.e. identifiers + reserved words), a string literal, or a numeric literal. It does not really matter whether you call it A or 'A' in the way of accessing it. https://ecma-international.org/ecma-262/6.0/#sec-object-initializer
Property names
Property names must be strings. This means that non-string objects
cannot be used as keys in the object. Any non-string object, including
a number, is typecasted into a string via the toString method.
var object = {};
object['1'] = 'value';
console.log(object[1]);
This outputs "value", since 1 is type-casted into '1'.
var foo = {unique_prop: 1}, bar = {unique_prop: 2}, object = {};
object[foo] = 'value';
console.log(object[bar]);
This also outputs "value", since both foo and bar are converted to the
same string. In the SpiderMonkey JavaScript engine, this string would
be "['object Object']".
Also what you are doing is basically creating an Object. I do not see you destroying it anywhere.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
Creating objects
However, the advantage of the literal or initializer notation is, that
you are able to quickly create objects with properties inside the
curly braces. You simply notate a list of key: value pairs delimited
by comma. The following code creates an object with three properties
and the keys are "foo", "age" and "baz". The values of these keys are
a string "bar", a number 42, and another object.
var object = {
foo: 'bar',
age: 42,
baz: {myProp: 12}
}
Accessing properties
Once you have created an object, you might want to read or change
them. Object properties can be accessed by using the dot notation or
the bracket notation. See property accessors for detailed information.
object.foo; // "bar"
object['age']; // 42
object.foo = 'baz';
One can think of an object as an associative array (a.k.a. map,
dictionary, hash, lookup table). The keys in this array are the names
of the object's properties. It's typical when speaking of an object's
properties to make a distinction between properties and methods.
However, the property/method distinction is little more than a
convention. A method is simply a property that can be called, for
example if it has a reference to a Function instance as its value.
I have declared an array a = [1,2,3,4,5]
When I write a[1] it returns 2 which is perfectly fine but when I write a['1'] it also gives me 2 instead of giving an error.
I was expecting an error there. Why does it behave like that??
All property names are strings.
If you pass a number, it gets converted to a string before being used to look up the property value.
console.log(1 == '1');
In JS an Array is basically an Object and thus mostly behaves like one. In this case, these are equivalent as long as you dont access Array's .length or try iterating a:
const a = {"0": foo};
const b = ["foo"];
Also this would work:
const a = ["foo"];
a.bar = "baz";
console.log(a);
So that a[1] and a['1'] are equivalent is exactly what's to be expected.
First of all, array is also object having property names as 0,1,2,....n
Property names must be strings. This means that non-string objects cannot be used as keys in the object. Any non-string object, including a number, is typecasted into a string via the toString method. [Ref]
var hello = 'hello';
Array.prototype.unshift.call(hello, '11') // gives error
Array.prototype.join.call(hello, ', ') // works, why??
can someone explain to me why .join works and why .unshift doesn't
Because strings are immutable, and unshift tries to assign to an index (property) of the string, as in
"hello"[4] = '1'
Reference: http://www.ecma-international.org/ecma-262/6.0/#sec-string-exotic-objects:
A String object is an exotic object that encapsulates a String value and exposes virtual integer indexed data properties corresponding to the individual code unit elements of the String value. Exotic String objects always have a data property named "length" whose value is the number of code unit elements in the encapsulated String value. Both the code unit data properties and the "length" property are non-writable and non-configurable.
join doesn't assign anything and only reads properties, therefore it works with any object that has .length.
Try this:
String.prototype.unshift = function(el) {
let arr = [this];
arr.unshift(el);
return arr.join("");
}
var s = "BCD";
s = s.unshift("A");
console.log(s); // ABCD
I'm trying to learn javascript (coming from Delphi/pascal) and am unclear about the similarities and differences between object properties and array values. I did try searching the archives and the web for this answer.
Consider the following code:
function Show(Arr) {
var str ='';
for (var Val in Arr) {
str += Val + '::' + Arr[Val] + '\n';
}
return str;
}
var str = '';
var A1 = ["Yellow", "Red", "Blue"];
var A2 = {"color":"red", "Size": 5, "taste":"sour"}
alert(Show(A1));
//OUTPUTS:
// 0::Yellow
// 1::Red
// 2::Blue
A1.push("Green");
alert(Show(A1));
//OUTPUTS:
// 0::Yellow
// 1::Red
// 2::Blue
// 3::Green
alert('Length: '+A1.length);
//OUTPUTS:
// Length: 4
alert(Show(A2));
//OUTPUTS:
// color::red
// Size::5
// taste:sour
alert('Length: '+A2.length);
//OUTPUTS:
// Length: undefined
A2.push("Green");
//ERROR --> execution stops on jsfiddle.net.
alert("OK"); //<-- never executed
alert(Show(A2)); //<-- never executed
I know that almost everything is an object in javascript. I have been reading here (http://javascript.info/tutorial/objects) and here (http://www.w3schools.com/js/js_objects.asp).
I see that an array can be accessed by index, e.g. A1[3] --> Blue, as in other languages. But I see also that a property can be accessed this way, e.g. A2["Size"] --> 5. So at first blush, it looks like array values and property values are essentially the same. But arrays can be extended with a .push(value) command, whereas properties can't.
It is coincidence that my Show function works for both arrays and objects?
Actually, as I have written this and researched the topic, is it just that all arrays are objects, but not all objects are array? So then does the for...in loop in Show() actually work differently depending on which type of object is sent in?
Any help clarifying this would be appreciated. Thanks.
So at first blush, it looks like array values and property values are essentially the same.
Array entries and object properties are indeed the same thing, because JavaScript's standard arrays aren't really arrays at all, they're just objects with some added features. Two of those features are the special length property, and the push function, which is why you don't see those with A2.
Your observation about bracketed notation is particularly spot-on. In JavaScript, you can access object properties using bracketed notation and a string, like this:
var o = {answer: 42};
console.log(o['answer']); // 42
It's not well-known that this is exactly what you're doing when using an array "index":
var a = ['a', 'b', 'c'];
console.log(a[1]); // b
The 1 we're using with a[1], technically according to the specification, is coerced to a string (a["1"]), and then that property name is used to look up the property on the object.
So then does the for...in loop in Show() actually work differently depending on which type of object is sent in?
No, for-in works the same with all objects. It iterates the names of the enumerable properties of the object. Whether you're using an array or any other object doesn't matter.
Note that not all properties are enumerable. For instance, Array#length isn't, nor is Array#push or Object#toString or any of the other built-in properties of objects.
But for instance, you can see that for-in is the same for arrays as for other objects like this:
var a = ['zero']; // An array with one entry
a.answer = 42; // We've added a property to the object that isn't an array entry
console.log(a.length); // 1, because `length` only relates to array "indexes" as
// defined by the specification
var key;
for (key in a) {
console.log(key + "=" + value);
}
// Shows (in *no reliable order*):
// 0=zero
// answer=42
More about for-in:
Myths and realities of for..in (on my blog)
My answer to the question For each in array, how to do that in JavaScript? here on SO
I'm not supposed to add elements to an array like this:
var b = [];
b.val_1 = "a";
b.val_2 = "b";
b.val_3 = "c";
I can't use native array methods and why not just an object. I'm just adding properties to the array, not elements. I suppose this makes them parallel to the length property. Though trying to reset length (b.length = "a string") gets Uncaught RangeError: Invalid array length.
In any case, I can still see the properties I've set like this:
console.log(b); //[val_1: "a", val_2: "b", val_3: "c"]
I can access it using the dot syntax:
console.log(b.val_1); //a
If an array is just an object in the same way a string or a number is an object, why can't (not that I'd want to) I attach properties to them with this syntax:
var num = 1;
num.prop_1 = "a string";
console.log(num); //1
I cannot access its properties using dot syntax
console.log(num.prp); //undefined
Why can this be done with array and not with other datatypes. For all cases, I should use {} and would only ever need to use {}, so why have arrays got this ability?
JSBIN
Because arrays are treated as Objects by the language, you can see this by typing the following line of code:
console.log(typeof []) // object
But other types like number literals, string literals NaN ... etc are primitive types and are only wrapped in their object reprsentation in certain contexts defined by the language.
If you want to add properties or methods to a number like that, then you can use the Number constructor like this:
var num = new Number(1);
num.prop_1 = "fdadsf";
console.log(num.prop_1);
Using the Number constructor returns a number object which you can see by typing the following line:
console.log(typeof num); // object
While in the first case:
var num = 1;
console.log(typeof num) // number
EDIT 2: When you invoke a method on a number literal or string literal for instance, then that primitive is wrapped into its object representation automatically by the language for the method call to take place, for example:
var num = 3;
console.log(num.toFixed(3)); // 3.000
Here num is a primitive variable, but when you call the toFixed() metohd on it, it gets wrapped to a Number object so the method call can take place.
EDIT: In the first case, you created a string like this first var str = new String(), but then you changed it to str = "asdf" and then assigned the property str.var_1 = "1234".
Of course, this won't work, because when you assigned str = "asdf", str became a primitive type and the Object instance that was originally created is now gone, and you can't add properties to primitives.
In the second, it didn't output undefined like you said, I tested it in Firebug and everything worked correctly.
EDIT 3:
String literals (denoted by double or single quotes) and strings returned from String calls in a non-constructor context (i.e., without using the new keyword) are primitive strings.
This is taken from MDN Documentation, when you use string like that var p = String(3) it becomes a conversion function and not a constructor and it returns a primitive string as you can see from the quote above.
Regarding your second comment, I didn't understand how my comment has been defied, because if you try to console.log(p.pr) you'll get undefined which proves p is a primitive type and not an object.
If an array is just an object in the same way a string or a number is an object,
An array is different than strings, numbers, booleans, null and undefined. An array IS an object, while the others in the list are primitive values. You can add properties to the array just like you would with any other object, anything different being just what makes arrays special (the length property you mentioned for example). You cannot add properties or call methods on primitive values.
In this previous answer i talked about the use of Object wrappers over primitive values. Feel free to read it to see more about Object wrappers. The following will be a very short example:
console.log('TEST'.toLowerCase()) // 'test'
While it may seem that the toLowerCase method is called on the string 'TEST', in fact the string is converted automatically to a String object and the toLowerCase method is called on the String object.
Each time a property of the string, number or boolean is called, a new Object wrapper of the apropriate type is created to get or set that value (setting properties might be optimized away entirely by the browser, i am not sure about that).
As per your example:
var num = 1; // primitive value
num.prop_1 = "a string"; // num is converted to a Number, the prop_1 property is set on the Object which is discarded immediately afterwards
console.log(num); //1 // primitive value
console.log(num.prp); // num is converted to a Number, which doesn't have the prp property
My example:
Number.prototype.myProp = "works!";
String.prototype.myFunc = function() { return 'Test ' + this.valueOf() };
Boolean.prototype.myTest = "Done";
console.log(true.myTest); // 'Done'
console.log('really works!'.myFunc()); // 'Test really works!'
var x = 3;
console.log(x.myProp.myFunc()); // 'Test works!'
console.log(3['myProp']); // 'works!'
On the other hand:
console.log(3.myProp); // SyntaxError: Unexpected token ILLEGAL
The number isn't necessarily treated differently, that syntax just confuses the parser. The following example should work:
console.log(3.0.myProp); // 'works!'