How to make mutation of a string? JavaScript - javascript

if objects are mutable by default why in this case it dosen't work?
How to make mutation value of the key "a" in the object "s"?
var s = {
a: "my string"
};
s.a[0] = "9"; // mutation
console.log(s.a); // doesn't work

You are trying to change a primitive String, which is immutable in Javascript.
For exmaple, something like below:
var myObject = new String('my value');
var myPrimitive = 'my value';
function myFunc(x) {
x.mutation = 'my other value';
}
myFunc(myObject);
myFunc(myPrimitive);
console.log('myObject.mutation:', myObject.mutation);
console.log('myPrimitive.mutation:', myPrimitive.mutation);
Should output:
myObject.mutation: my other value
myPrimitive.mutation: undefined
But you can define a function in primitive String's prototype, like:
String.prototype.replaceAt=function(index, replacement) {
return this.substr(0, index) + replacement+ this.substr(index + replacement.length);
}
var hello="Hello World"
hello = hello.replaceAt(2, "!!")) //should display He!!o World
Or you can just assign another value to s.a, as s.a = 'Hello World'

Strings in JavaScript are immutable. This means that you cannot modify an existing string, you can only create a new string.
var test = "first string";
test = "new string"; // same variable now refers to a new string

You try to mutate a string which not possible, because strings are immutable. You need an assignment of the new value.
Below a fancy style to change a letter at a given position.
var s = { a: "my string" };
s.a = Object.assign(s.a.split(''), { 0: "9" }).join('');
console.log(s.a);

You are trying to mutate the string using element accessor, which is not possible. If you apply a 'use strict'; to your script, you'll see that it errors out:
'use strict';
var s = {
a: "my string"
};
s.a[0] = '9'; // mutation
console.log( s.a ); // doesn't work
If you want to replace the character of the string, you'll have to use another mechanism. If you want to see that Objects are mutable, simply do s.a = '9' instead and you'll see the value of a has been changed.
'use strict';
var s = {
a: "my string"
};
s.a = s.a.replace(/./,'9')
console.log(s.a);

Related

2 Objects (created via new keyword for String) on addition NOT giving [Object][Object] (JavaScript)

This question is based on previous question:
Difference in these 2 Strings (JavaScript)
The people replied that there is a difference by creating string via 2 separate ways:
String Literal creates string (var a = "abc")
new keyword creates string-object, I assume it is a kind of object (var b = new String("def"))
Now, typeof in 1st case will return string. In 2nd case it will return Object. I am okay, there might be certain way of working, of JS engine, by the people who developed it.
But, then, in the following example why the hell I am getting the answer in last line as abcdef. Now, that too should have consoled [object][object], as the line above. Now I am really confused, new String is either creating a string, or object or what? It is just NOT consistent!
Can someone help me explain?
var obj1 = new Object({name: "Peter"});
var obj2 = new Object({age: 29});
var str1 = new String("abc");
var str2 = new String("def");
console.log(obj1);
console.log(obj2);
console.log(str1);
console.log(str2);
console.log(obj1 + obj2);
console.log(str1 + str2);
new String creates a String object, which inherits from Object, but has its own .toString and .valueOf methods, so it will print the string content.
var o = new Object();
var s = new String("foo");
console.log(o.toString === s.toString); // false
console.log(o.valueOf === s.valueOf); // false
You can override them with your own to see that they're invoked. Just be sure to invoke the originals too.
var s = new String("foo");
s.valueOf = function() {
console.log("custom valueOf");
return String.prototype.valueOf.call(this);
}
s.toString = function() {
console.log("custom toString");
return String.prototype.toString.call(this);
}
console.log(s + s);
[""].join(s);
But, then, in the following example why the hell I am getting the answer in last line as abcdef. Now, that too should have consoled [object][object], as the line above.
The difference is a String object has a default valueOf method that returns the string value contained within the object.
The Object object has a more generic valueOf method which simply returns a string of [object Object]
See -
const one =
{ valueOf: _ => 1 }
const two =
{ valueOf: _ => 2 }
console.log(one + two)
// 3
You can define valueOf to be anything -
const foo =
{ valueOf: _ => "foo" }
const bar =
{ valueOf: _ => "bar" }
console.log(foo + bar)
// "foobar"

Execute function off of variable

I am quite newish at nodejs and javascript in general, and I have been trying to figure out how to make a function that executes on a variable, e.g.
var string = "Hello there";
var string1 = "Hello there again"
string = string.function();
string1 = string.function();
I am aware that this can be achieved by doing something like this function(string);, but I am a massive fan of more "inline code" and would like a nicer way to do it.
To achieve this you make your string variable an object
var string = {
text: "Hello there",
func: function(value) {
return value;
}
}
string.func(string.text); // Hello there
Edit: If you want your function to work on all strings add a method in String.prototype like so
String.prototype.your_function = function (char) {
// work on char here
return char
};
You can add custom functions to built in JavaScript object prototypes to your need.
For example in the case of your string approach, you can add a custom property to String.prototype like this:
String.prototype.myFunction = function() {
return 'Value from myFunction: ' + this.valueOf();
}
And when you declare a string you can go and call your new function inline:
var s = 'my string';
s.myFunction();
And it will return:
"Value from myFunction: my string"
Hope it helps!
I think this what you need
String.prototype.function = function ()
{
return this + " world";
};
var x = "hello";
var y = x.function();
console.log(y);

New JS Library, how to improve it?

I'm trying to improve on a small library I'm starting to write:
var syn=(function(){
var container = {};
return function(variable){
return{
val: container[variable],
is: function(value){
container[variable] = value;
}
};
};
})();
Currently it's capable of storing snippets of information using the syntax syn("a").is(42); and returning the value by using syn("a").val.
I'd like to be able to do two things with this library:
I'd like to be able to create new instances of the syn object, so I could create multiple "synapses". e.g., var SynapseA = new syn;
I'd like to reduce syn("a").val to just syn("a") so that if I refer to syn("a") without a property or method it returns the equivalent of syn("a").val, but I have no idea how this would be done?
Appreciate any help...
What you want is not possible, because it is in some way contradictory:
I'd like to reduce syn("a").val to just syn("a") so that if I refer to syn("a") without a property or method it returns the equivalent of syn("a").val
Assume this were possible, and the value stored for "a" is 42 as in your example, then both of the following expressions would need to return 42:
syn("a")
syn("a").val
But if the first returns 42, then the second can't work: 42 does not have a property val. If the second works, then the first will necessarily return an object with a val property, which obviously is not what 42 is. So this is a contradiction.
In my opinion, the closest you can get to what you want, is relying on the special valueOf method, which will kick in when you force coercion to a number (or boolean). However, for this to work, you must assume that the values you store, are indeed numbers.
Here is how it would work:
function Syn() { // constructor, so you can create more than 1 syn object
var container = {};
var f = function(variable){
return {
valueOf: function() { // special method
return container[variable];
},
val: container[variable],
assign: function(value){
container[variable] = value;
}
}
};
// Only include next line, if you REALLY need the returned
// object to be considered an instance of Syn:
Object.setPrototypeOf(f, Object.getPrototypeOf(this));
return f;
}
var syn = new Syn();
console.log(syn instanceof Syn); // true
syn("a").assign(42);
console.log(syn("a").val); // 42
console.log(+syn("a")); // 42, because `syn("a")` is coerced to number
NB: I renamed the method is to assign, as that seems more meaningful.
Similarly to valueOf, you could rely on toString, which does a similar thing when you coerce the return value of syn("a") to string:
function Syn() { // constructor, so you can create more than 1 syn object
var container = {};
var f = function(variable){
return {
toString: function() { // special method
return container[variable];
},
val: container[variable],
assign: function(value){
container[variable] = value;
}
}
};
// Only include next line, if you REALLY need the returned
// object to be considered an instance of Syn:
Object.setPrototypeOf(f, Object.getPrototypeOf(this));
return f;
}
var syn = new Syn();
console.log(syn instanceof Syn); // true
syn("a").assign("hello");
console.log(syn("a").val); // "hello"
console.log(''+syn("a")); // "hello", because `syn("a")` is coerced to string
This will do what you're asking I think:
var syn = function() {
this.container = {};
}
syn.prototype.is = function(index, value){
this.container[index] = value;
}
syn.prototype.val = function(index){
return this.container[index];
}
I can do the following:
var synapseA = new syn();
synapseA.is("a", 42);
console.log(synapseA.val("a"));
var synapseB = new syn();
synapseB.is("a", 30);
console.log(synapseB.val("a"));
synapseB.is("b", 20);
console.log(synapseB.val("b"));
And I get 42, 30 and 20 logged out. Is this what you're after?

Automatically updating the actual parameters in javascript

How to pass a primitive variable (like a string) by reference when calling a java script method?
Which is equivalent of out or ref keyword in C#.
I have a variable like var str = "this is a string"; and passing the str into my function and automatically have to reflect the change in str when i change the argument value
function myFunction(arg){
// automatically have to reflect the change in str when i change the arg value
arg = "This is new string";
// Expected value of str is "This is new string"
}
Primitive types, that is strings/numbers/booleans are passed by value.
Objects such as functions, objects, arrays are "passed" by reference.
So, what you want won't be possible, but the following will work:
var myObj = {};
myObj.str = "this is a string";
function myFunction(obj){
// automatically have to reflect the change in str when i change the arg value
obj.str = "This is new string";
// Expected value of str is "This is new string"
}
myFunction(myObj);
console.log(myObj.str);

Access JSON or JS property using string

I have a JSON array like this:
_htaItems = [
{"ID":1,
"parentColumnSortID":"0",
"description":"Precondition",
"columnSortID":"1",
"itemType":0},
{"ID":2,
"parentColumnSortID":"0",
"description":"Precondition",
"columnSortID":"1",
"itemType":0}]
I want to update this by passing the ID, column name and new value to a function:
function updateJSON(ID, columnName, newValue)
{
var i = 0;
for (i = 0; i < _htaItems.length; i++)
{
if (_htaItems[i].ID == ID)
{
?????
}
}
}
My question is, how do I update the value? I know I can do something like the following:
_htaItems[x].description = 'New Value'
But in my cause, the column name is being passed as a string.
In JavaScript, you can access an object property either with literal notation:
the.answer = 42;
Or with bracketed notation using a string for the property name:
the["answer"] = 42;
Those two statements do exactly the same thing, but in the case of the second one, since what goes in the brackets is a string, it can be any expression that resolves to a string (or can be coerced to one). So all of these do the same thing:
x = "answer";
the[x] = 42;
x = "ans";
y = "wer";
the[x + y] = 42;
function foo() {
return "answer";
}
the[foo()] = 42;
...which is to set the answer property of the object the to 42.
So if description in your example can't be a literal because it's being passed to you from somewhere else, you can use bracketed notation:
s = "description";
_htaItems[x][s] = 'New Value';
_htaItems[x][columnName] = 'New Value';
Or did I misunderstand you?
Just do _htaItems[i][columnName] = newValue;. It will change the property specified in columnName to newValue.
You need to use square bracket notation, just like you did for array index:
_htaItems[i][columnName] = newValue;

Categories