JavaScript Array map function won't change elements in a String? - javascript

So I've tried to use the map() method as follows:
words = ["One", "Two"];
words = words.map(function(currentValue)
{
alert(currentValue[0]);//Output: O Then: T
currentValue[0] = "A";
alert(currentValue[0]);//Output: O Then: T
return currentValue;
});
Why is it that currentValue[0] is not getting assigned the value "A"?!?

Your attempting to assign to a string at a specific position via its index, this is not possible as Strings are immutable. If you want to change a string you need to create a new one.

As Alex K correctly points out, strings are immutable and you cannot modify them.
Since you are using a .map(), the thing to do here is just construct a new string and return that:
var words = ["One", "Two"];
words = words.map(function (currentValue) {
return "A" + currentValue.substring(1);
});
console.log(words); // outputs ["Ane", "Awo"];
As a rule of thumb, you should not try to use .map() to modify existing values. The purpose of .map() is to produce a new set of values, and leave the original ones untouched.

In JavaScript String is the primitive type, so you cannot mutate it.
String , Number , Boolean, Null, Undefined, Symbol (new in ECMAScript 6) are primitive types.

Related

Array unshift for string in javascript

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

How to access an element of an array without using indexer (javascript)?

Let's say I have a single element array ["someStringHere"] (I don't know in advance what the string will be) and I want to access the string so that my function returns the string and not the array, how could I do so without using an indexer (ex: array[0])?
In other words, it would be as if I could delete the brackets so that I just had the string.
Every object has a toString method. You could go about using this method, though it's confusing why you'd want to. Another option is the join method.
var someArr = ['some string here'];
console.log(someArr.toString());
console.log(someArr.join());
According to MDN:
The Array object overrides the toString method of Object. For Array
objects, the toString method joins the array and returns one string
containing each array element separated by commas.
See here for specifics.
Amusingly, that works just by forcing it to a string type:
var someArr = ['some string here'];
console.log( "" + someArr );
And one more for the road:
someArr.forEach (function (s) { console.log(s) });

adding properties to primitive data types other than Array

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!'

what is the equivalent JavaScript function for VBScript CreateObject()

What is the JavaScript equivalent function for CreateObject("Scripting.Dictionary")?
I have to convert following two statements from VBScript to JavaScript, anyone can help me to find a solution.
Set oInvoicesToCreate = CreateObject("Scripting.Dictionary")
If Not oInvoicesToCreate.Exists(cInvoiceID) Then
oInvoicesToCreate(CStr(cInvoiceID)) = ""
End If
var oInvoicesToCreate = {};
if(oInvoicesToCreate[cInvoiceID] === undefined){
oInvoicesToCreate[cInvoiceID] = "";
}
You probably don't want to check the hasOwnProperty method because you'll want to check if anything in the prototype chain has that property as well and not overwrite it. checking with the []s will let you know if any property on any prototype items have the property as well.
As bluetoft says in this answer, in Javascript you can use a plain object instead. However, there are a few differences between them that you should be aware of:
First, a Dictionary's keys can be any type:
var dict = new ActiveXObject('Scripting.Dictionary');
dict(5) = 'Athens';
console.log(dict('5')); //prints undefined
whereas any value used for a Javascript object's key will be converted to a string first:
var obj = {};
obj[5] = 'Athens';
console.log(obj['5']); // prints 'Athens'
From MDN:
Please note that all keys in the square bracket notation are converted to String type, since objects in JavaScript can only have String type as key type. For example, in the above code, when the key obj is added to the myObj, JavaScript will call the obj.toString() method, and use this result string as the new key.
Second, it is possible to set a Dictionary to treat differently cased keys as the same key, using the CompareMode property:
var dict = new ActiveXObject('Scripting.Dictionary');
dict.CompareMode = 1;
dict('a') = 'Athens';
console.log(dict('A')); // prints 'Athens'
Javascript key access via [] doesn't support this, and if you want to treat differently-cased keys as the same, you'll have to convert the potential key to lowercase or uppercase before each read or write.
For your specific scenario, neither of these differences matter, because the keys are numeric strings (1) which have no case (2).

Javascript Array 'Literal' - Is that just describing how its created since it can be changed on the fly?

I don't understand why Mozilla calls this an Array 'Literal' when it's defined using the VARIABLE keyword and it can be completely changed...
var coffees = ["French Roast", "Colombian", "Kona"];
Can anyone explain this to me?
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Core_Language_Features#Object_literals
You are confusing literal and constant.
A constant doesn't change, but a literal just means you are explicitly setting the array values as a whole.
In other words, you are defining what you literally want the array value to be. The literal itself (on the right side) is constant, but you are assigning it to a variable. In the same way you could assign the value of a constant to a variable.
There are literals for pretty much every data type.
var myNumber = 42; // Number literal
var myString = "Thanks for all the fish"; // String literal
var myObject = { dolphins: 1, humans: 2 }; // Object literal
It is a literal because you use the square brackets var arr = []; to initialize the array as opposed to using var arr = new Array();
It's the same way {} is a literal for objects
A literal is an opposition to a constructor and is simply a convenient language construct.
If you google "literals vs constructors" you will find quite a few pages regarding the subject :)
You can also read more on js literals here: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Core_Language_Features#Literals
The written, literal value ["French Roast", "Colombian", "Kona"] actually can't be changed -- it's an array with those exact three strings, and nothing else. Once the literal is stored in a variable, the value of the variable can change, so the variable is non-literal.
You can even change the value of the structure represented by the literal on the fly, e.g., [1,2,3].push(4), but even so, the written value of [1,2,3] is a literal that refers to an array with those three elements.
It's much like using numeric literals, e.g.,in a = 1 + 2 the expressions 1 and 2 are unchangeable literals, but they can be combined to produce new results (and obviously the value of a can change).
The term "literal" just means "here is the array, right here, the whole thing". A non-literal way of creating the same array could be:
var coffees = new Array();
coffees.push("French Roast");
coffees.push("Colombian");
coffees.push("Kona");
The main reason the term array literal gets brought up is that creating an array using the [] literal or the Array() constructor is not guaranteed to produced the same results all of the time. This is because the Array() constructor could be altered or even replaced by a script. Consider this example:
Array = function() {
var n = 0;
for (var i=0, l=arguments.length; i<l; i++) {
n += arguments[i];
}
return n;
}
var myArray = Array(1,2,3); // myArray type is number, value 6, probably not what you'd want
Versus
var myArray = [1,2,3]; // myArray type is object, value [1,2,3], probably what you'd want
So in addition to the literal syntax being more concise, it is also 100% predicable.

Categories

Resources