Changing the first(or any) character of an array string value - javascript

Say I have an array with string values such as:
var foo = ["Hello", "World"];
I can return the first character of each array element by doing:
foo[0][0]; // Will return "H"
foo[1][0]; // Will return "W"
However, when attempting to change the value of those characters using a similar method, it doesn't work. What I mean is that doing this does not work:
foo[0][0] = "J"; // Will not change "H" to "J".
It's not a huge issue since I know alternative ways to do so such as:
foo[0] = "J"+foo[0].substsring(1); // Hello --> Jello
But I'm curious as to why the previous method does not work? EDIT: Did some fiddling around and apparently it doesn't work with strings at all to begin with, not just strings in arrays. I guess I was under the false impression that strings act just like arrays. I can return certain characters by calling it's position in the string similar to how calling an array index works, but changing said index doesn't hold.

From Javascript String reference:
For character access using bracket notation, attempting to delete or
assign a value to these properties will not succeed. The properties
involved are neither writable nor configurable. (See
Object.defineProperty() for more information.)

Strings are immutable, that is, they cannot be altered.
This:
foo[0][0] = "J";
Doesn't work because you are attempting to modify the string stored at position 0 in the foo array.
This:
foo[0] = "J"+foo[0].substsring(1);
does work because you aren't trying to modify a string, you are trying to replace the element at position 0 in the foo array with an entirely new string.

All primitive data types in JavaScript are immutable.
Quote from MDN:
Unlike in languages like C, JavaScript strings are immutable. This means that once a string is created, it is not possible to modify it. However, it is still possible to create another string based on an operation on the original string.

Strings are immutable, so they cannot be changed unless you create a new string and store the new value inside of that string. You cannot change a character within a string, The string manipulation methods such as trim, substring etc.
From substring method - The result is a String value, not a String object.
var foo = ["Hello", "World"];
foo[0][0] = "J";
console.log(foo);
foo[0] = "J"+foo[0].substring(1);
console.log(foo);
Notice if you change
var foo = [1, "World"];
foo[0][0] = "J";
It works, since it's not a string
Check this out : https://tc39.github.io/ecma262/#sec-string.prototype.substring
If start is larger than end, they are swapped.
The following steps are taken: From the link above
Let O be ? RequireObjectCoercible(this value).
Let S be ? ToString(O).
Let len be the number of elements in S.
Let intStart be ? ToInteger(start).
If end is undefined, let intEnd be len; else let intEnd be ? ToInteger(end).
Let finalStart be min(max(intStart, 0), len).
Let finalEnd be min(max(intEnd, 0), len).
Let from be min(finalStart, finalEnd).
Let to be max(finalStart, finalEnd).
Return a String whose length is to - from, containing code units from S, namely the code units with indices from through to - 1, in ascending order.

Related

Using negative values as index in Arrays in JavaScript [duplicate]

Why negative indexing of an array in JS doesn't raise an error? It looks like it not intended to have elements with a negative index in an array:
array.length doesn't count elements with negative indices.
array.forEach() doesn't iterate over elements with negative indices.
UPD. The question is not "why it is thechnically possible" buth rather "why it is allowed by design".
[RESOLVED] Short answer: there is no particular reason, it just happened to become like this.
Arrays are the special type of object in JavaScript. It has an extra list of methods and properties (like .length and .forEach), and also it has a list of used indexes (integer positive number starting from zero higher).
But just like any other object, it can have additional properties:
var arr = ['A', 'B'];
arr.extra = 'C';
console.log(arr[0], arr[1], arr.extra); // A B C
Because of object properties can be accessed not only via dot but also via square brackets you can access any property using array-like syntax:
var obj = { extra: 'D' };
console.log(obj['extra']); // D
console.log(arr['extra']); // C
Using the same syntax you can assign properties:
obj['x'] = 'E';
obj[33] = 'F';
arr['y'] = 'G';
arr[-1] = 'H';
console.log(obj.x, obj[33], arr.y, arr[-1]); // E F G H
You can safely use numbers as a property name for the object, it will automatically be converted to a string.
The only difference is when you use positive integer values for the name of the property. Those are interpreted as array indexes.
var arr = [];
arr[0] = 'A';
arr[1] = 'B';
arr[-1] = 'C';
arr.forEach(value => console.log(value)) // A, B
console.log(arr.length); // 2
console.log( Object.keys(arr) ); // ["0", "1", "-1"]
Arrays in javascript also can work as hash objects (as almost all objects in js including functions). So doing: a[-1] = -1 simply defines a new key in the array (as object hash) with key value "-1" and value -1.
You should know that almost all objects in javascript can be used as hash objects as well. This is what you see. However these keys (which are not positive integers) for arrays do not count as array keys in the normal sense, only as hash keys.
JS allows negative indices in an array for the simple reason that they are objects under the hood. You can also put [].blah = 5 and it would be valid but a terrible idea.

What does Array.prototype.join.call do in the background for a string?

var a = "foo";
var c = Array.prototype.join.call( a, "-" ); // 'f-o-o'
How does the second line of code work? I don't see any conversion of the string to an array and then converting back again, is this happening in the background? I've encountered this kind of code and it's very weird, an array method accepting a string.
See the specification for Array.prototype.join (below). It doesn't require that the this it's operating on be an array, merely that it have a length and properties with names like 0, 1, and so on. Strings do, and so join can work on a string.
From the spec:
NOTE 2 The join function is intentionally generic; it does not require that its this value be an Array object. Therefore, it can be transferred to other kinds of objects for use as a method.
Here's the full algorithm from the spec:
Let O be ToObject(this value).
ReturnIfAbrupt(O).
Let len be ToLength(Get(O, "length")).
ReturnIfAbrupt(len).
If separator is undefined, let separator be the single-element String ",".
Let sep be ToString(separator).
ReturnIfAbrupt(sep).
If len is zero, return the empty String.
Let element0 be Get(O, "0").
If element0 is undefined or null, let R be the empty String; otherwise, let R be ToString(element0).
ReturnIfAbrupt(R).
Let k be 1.
Repeat, while k < len
Let S be the String value produced by concatenating R and sep.
Let element be Get(O, ToString(k)).
If element is undefined or null, let next be the empty String; otherwise, let next be ToString(element).
ReturnIfAbrupt(next).
Let R be a String value produced by concatenating S and next.
Increase k by 1.
Return R.
A string is an Array like object, because it has the property length and you can access its elements (chars) using [] as of that you can apply most of the array manipulation operations on it.
The Function.prototype.call() calls the function given function with using the first parameter as this and the flowing one as normal parameters.
As of that Array.prototype.join.call(a, "-") will call the function join on the object a in you case the string.
String is array-like object. An array-like object provides indexed access to elements and the property length. You can read more here

Javascript assigning a method to an array value

I'm trying to figure out why I cannot assign the toUpperCase method to a specific value in an array (see below). I am a little confused because I thought objects were mutable and manipulated by reference? Maybe I am looking at it backwards?
var ary = ["hello", "there", "world"];
ary[0][0] = ary[0][0].toUpperCase();
console.log(ary[0][0]); // returns lowercase h
Any clarification would help me out a lot.
Since Strings are immutable in JavaScript, assigning a new character to an index of a String will not change the string at all. You need to create a new String like this
ary[0] = ary[0][0].toUpperCase() + ary[0].substr(1);
# H
We are creating a new string with the first letter capitalized and the rest of the string as it is.

Javascript accessing the string variable as array

I just tried this code in Chrome deveoper tools:
var str = "1111111";
str[0] = 2;
2
console.log(str[0]);
1
As you can see, the output was 1, where I expected 2. My conclusion is this is not meant to be working like that, so I ask how would I get this to work - how would I change the first 'item' of the varable str to 2?
That is because in JavaScript strings are immutable objects. You should use substr function:
String.prototype.replaceAt = function (index, char) {
return this.substr(0, index) + char + this.substr(index + char.length);
};
var str = '11111';
console.log(str.replaceAt(0, '2'));
From the rhino book:
In JavaScript, strings are immutable objects, which means that the characters within them may not be changed and that any operations on strings actually create new strings. Strings are assigned by reference, not by value. In general, when an object is assigned by reference, a change made to the object through one reference will be visible through all other references to the object. Because strings cannot be changed, however, you can have multiple references to a string object and not worry that the string value will change without your knowing it.
Try this out
str.replace(str.charAt(0), "2")
You need to split the string first.
So something like:
str = str.split('');
Then you can treat it as an array.

JavaScript: Use Object As Array

Are there any pitfalls to code like this?
var Foo = function() {
this.bar = function() { return 'bar'; };
};
var f = new Foo();
f[0] = 'hi';
f[1] = 'there';
Note that I'm creating a new function object with some misc properties, and then I'm treating the object like an array. Also how are the array values being stored in the object? Are 0 and 1 treated like property names?
Well, yes, 0, and 1 will be just two property names.
When you assign a property with the bracket notation, the expression between the brackets will be converted to String, and that string will be used as the property name.
In fact, even the indexes for real arrays are just that, properties:
var realArray = ['a'];
realArray.hasOwnProperty('0'); // true
The difference is that real array objects on every property assignment that correspond to a valid index[1], track internally the value of their length property.
That's one of the reasons why "subclassing" array objects is difficult, even with the new ECMAScript 5 extensions, or at the moment also with the proposed ECMAScript-Harmony Proxies 2 3, can't be completely done, in a stanard way.
That can be a problem, depending on how you plan to iterate the numeric properties.
If you enumerate the properties with the for-in statement, other members will appear, not just the numeric properties.
[1] A valid array index is any unsigned 32-bit integer in the range of 0 to (2^32)-1.
I think you might have problems if you try to loop through that with a for in loop; the loop will also get bar. There are ways around this, so you just have to be careful.
If you want to extend Array behavious please use : Array.prototype.yourfunc = function()....

Categories