I did search this info on the web, some say yes because javascript must create a new string object to store the result of the concatenation, some say no because string objects are not collected.
Maybe it depends on the context. For example, if I had an array of objects like
animals["blue_dog","red_dog","yellow_cat","red_bird","green_bird"...]
and I had a function with animal and color arguments, in this function I would access my object like this:
animals[animal+"_"+color].
Most of the time I do concatenations when drawing text, which obviously doesn't happen a lot of times per frame. So even if it becomes garbage, it is insignificant. But when using a concatenation as an object's key, because of loops this concatenation could happen a thousand times per frame, and then this may become a problem.
Doing something like animals[color + "_" + animal] creates a temporary value for accessing the object. That temporary will be collected either by the garbage collector or at the end of the block/function call (implementation dependent).
My assumption (based on my own experience in working with compilers) is that since the result isn't stored in a variable, it will be placed on the stack and released once the function completes. But, again, this depends on how the engine is written.
I'm in no way an expert on compilers.
May or may not, depends on how optimal is the compiler.
This a + b + c is (a + b) + c so you have two concatenations. Result of (a + b) will be a temporary object (string here). That temporary is a garbage.
For the given expression this form a.concat(b,c) is conceptually better. It in principle does not require intermediate temporaries.
In my experience, concatenating strings can definitely produce garbage. I had a scenario where I had a lot of cells in a large table and each cell could have a different css class (from a set of combinations of maybe 30 different combinations) assigned. Doing this the normal way:
const class = group + empty + active;
Would produce a lot of garbage. I created a memoized function that received a bitmask as argument which would produce the class string and got rid of the garbage that way.
This reply is an excellent list of what to avoid:
https://stackoverflow.com/a/18411275
Related
Consider the below snippet, which converts an array of objects to an array of numbers, with negative values filtered out, and then doubled by 2:
var objects = (new Array(400)).fill({
value: Math.random() * 10 - 5
});
var positiveObjectValuesDoubled = objects.map(
item => item.value
).filter(
value => value > 0
).map(
value => value * 2
);
When chained together like this, how many actual Array objects are created in total? 1, or 3? (excluding the initial objects array).
In particular, I'm talking about the intermediary Array objects created by filter, and then by the second map call in the chain: considering these array objects are not explicitly referenced per se, are Javascript runtimes smart enough to optimize where possible in this case, to use the same memory area?
If this cannot be answered with a clear yes-or-no, how could I determine this in various browsers? (to the best of my knowledge, the array constructor can no longer be overridden, so that's not an option)
Good commentary so far, here's a summary answer: an engine might optimize for memory usage across chained method calls, but you should never count on an engine to do optimization for you.
As your example of chained methods is evaluated, the engine's memory heap is affected in the same order, step by step (MDN documentation on the event loop). But, how this works can depend on the engine...for some Array.map() might create a new array and garbage collect the old one before the next message executes, it might leave the old one hanging around until the space is needed again, it might change an array in place, whatever. The rabbithole for understanding this is very deep.
Can you test it? Sometimes! jQuery or javascript to find memory usage of page, this Google documentation are good places to start. Or you can just look at speed with something like http://jsperf.com/ which might give you at least an idea of how space-expensive something might be. But you could also use that time doing straightforward optimization in your own code. Probably a better call.
If a string is immutable, does that mean that....
(let's assume JavaScript)
var str = 'foo';
alert(str.substr(1)); // oo
alert(str); // foo
Does it mean, when calling methods on a string, it will return the modified string, but it won't change the initial string?
If the string was mutable, does that mean the 2nd alert() would return oo as well?
It means that once you instantiate the object, you can't change its properties. In your first alert you aren't changing foo. You're creating a new string. This is why in your second alert it will show "foo" instead of oo.
Does it mean, when calling methods on
a string, it will return the modified
string, but it won't change the
initial string?
Yes. Nothing can change the string once it is created. Now this doesn't mean that you can't assign a new string object to the str variable. You just can't change the current object that str references.
If the string was mutable, does that
mean the 2nd alert() would return oo
as well?
Technically, no, because the substring method returns a new string. Making an object mutable, wouldn't change the method. Making it mutable means that technically, you could make it so that substring would change the original string instead of creating a new one.
On a lower level, immutability means that the memory the string is stored in will not be modified. Once you create a string "foo", some memory is allocated to store the value "foo". This memory will not be altered. If you modify the string with, say, substr(1), a new string is created and a different part of memory is allocated which will store "oo". Now you have two strings in memory, "foo" and "oo". Even if you're not going to use "foo" anymore, it'll stick around until it's garbage collected.
One reason why string operations are comparatively expensive.
Immutable means that which cannot be changed or modified.
So when you assign a value to a string, this value is created from scratch as opposed to being replaced. So everytime a new value is assigned to the same string, a copy is created. So in reality, you are never changing the original value.
I'm not certain about JavaScript, but in Java, strings take an additional step to immutability, with the "String Constant Pool". Strings can be constructed with string literals ("foo") or with a String class constructor. Strings constructed with string literals are a part of the String Constant Pool, and the same string literal will always be the same memory address from the pool.
Example:
String lit1 = "foo";
String lit2 = "foo";
String cons = new String("foo");
System.out.println(lit1 == lit2); // true
System.out.println(lit1 == cons); // false
System.out.println(lit1.equals(cons)); // true
In the above, both lit1 and lit2 are constructed using the same string literal, so they're pointing at the same memory address; lit1 == lit2 results in true, because they are exactly the same object.
However, cons is constructed using the class constructor. Although the parameter is the same string constant, the constructor allocates new memory for cons, meaning cons is not the same object as lit1 and lit2, despite containing the same data.
Of course, since the three strings all contain the same character data, using the equals method will return true.
(Both types of string construction are immutable, of course)
The text-book definition of mutability is liable or subject to change or alteration.
In programming, we use the word to mean objects whose state is allowed to change over time. An immutable value is the exact opposite – after it has been created, it can never change.
If this seems strange, allow me to remind you that many of the values we use all the time are in fact immutable.
var statement = "I am an immutable value";
var otherStr = statement.slice(8, 17);
I think no one will be surprised to learn that the second line in no way changes the string in statement.
In fact, no string methods change the string they operate on, they all return new strings. The reason is that strings are immutable – they cannot change, we can only ever make new strings.
Strings are not the only immutable values built into JavaScript. Numbers are immutable too. Can you even imagine an environment where evaluating the expression 2 + 3 changes the meaning of the number 2? It sounds absurd, yet we do this with our objects and arrays all the time.
Immutable means the value can not be changed. Once created a string object can not be modified as its immutable. If you request a substring of a string a new String with the requested part is created.
Using StringBuffer while manipulating Strings instead makes the operation more efficient as StringBuffer stores the string in a character array with variables to hold the capacity of the character array and the length of the array(String in a char array form)
From strings to stacks... a simple to understand example taken from Eric Lippert's blog:
Path Finding Using A* in C# 3.0, Part Two...
A mutable stack like System.Collections.Generic.Stack
is clearly not suitable. We want to be
able to take an existing path and
create new paths from it for all of
the neighbours of its last element,
but pushing a new node onto the
standard stack modifies the stack.
We’d have to make copies of the stack
before pushing it, which is silly
because then we’d be duplicating all
of its contents unnecessarily.
Immutable stacks do not have this problem. Pushing onto an immutable
stack merely creates a brand-new stack
which links to the old one as its
tail. Since the stack is immutable,
there is no danger of some other code
coming along and messing with the tail
contents. You can keep on using the
old stack to your heart’s content.
To go deep on understaning immutability, read Eric's posts starting with this one:
Immutability in C# Part One: Kinds of Immutability
One way to get a grasp of this concept is to look at how javascript treats all objects, which is by reference. Meaning that all objects are mutable after being instantiated, this means that you can add an object with new methods and properties. This matters because if you want an object to be immutable the object can not change after being instantiated.
Try This :
let string = "name";
string[0] = "N";
console.log(string); // name not Name
string = "Name";
console.log(string); // Name
So what that means is that string is immutable but not constant, in simple words re-assignment can take place but can not mutate some part.
The text-book definition of mutability is liable or subject to change or alteration. In programming, we use the word to mean objects whose state is allowed to change over time. An immutable value is the exact opposite – after it has been created, it can never change.
If this seems strange, allow me to remind you that many of the values we use all the time are in fact immutable.
var statement = "I am an immutable value"; var otherStr = statement.slice(8, 17);
I think no one will be surprised to learn that the second line in no way changes the string in statement. In fact, no string methods change the string they operate on, they all return new strings. The reason is that strings are immutable – they cannot change, we can only ever make new strings.
Strings are not the only immutable values built into JavaScript. Numbers are immutable too. Can you even imagine an environment where evaluating the expression 2 + 3 changes the meaning of the number 2? It sounds absurd, yet we do this with our objects and arrays all the time.
Objects in JavaScript have unique identities. Every object you create via an expression such as a constructor or a literal is considered differently from every other object.
What is the reason behind this?
{}==={}//output:false
For what reason they are treated differently? What makes them different to each other?
{} creates a new object.
When you try and compare two, separate new objects (references), they will never be equal.
Laying it out:
var a = {}; // New object, new reference in memory, stored in `a`
var b = {}; // New object, new reference in memory, stored in `b`
a === b; // Compares (different) references in memory
If it helps, {} is a "shortcut" for new Object(), so more explicitly:
var a = new Object();
var b = new Object();
a === b; // Still false
Maybe the explicitness of new helps you understand the comparison compares different objects.
On the other side, references can be equal, if they point to the same object. For example:
var a = {};
var b = a;
a === b; // TRUE
They are different instances of objects, and can be modified independently. Even if they (currently) look alike, they are not the same. Comparing them by their (property) values can be useful sometimes, but in stateful programming languages the object equality is usually their identity.
The fact that they're different is important in this scenario:
a={};
b={};
a.some_prop = 3;
At this point you'll obviously know that b.some_prop will be undefined.
The == or === operators thus allow you to be sure that you're not changing some object's properties, that you don't want changed
This question is quite old, but I think the actual solution does not pop out clearly enough in the given answers, so far.
For what reason they are treated differently? What makes them
different to each other?
I understand your pain, many sources in the internet do not come straight to the fact:
Object (complex JS types => objects, arrays and functions) variables store only references (=address of the instances in memory) as their value. Object identity is recognized by reference identity.
You expected something like an ID or reference inside the object, which you could use to tell them apart (maybe that's actually done transparently, under the hood). But every time you instantiate an object, a new instance is created in memory and only the reference to it is stored in the variable.
So, when the description of the ===-operator says that it compares the values, it actually means it compares the references (not the properties and their values), which are only equal if they point to the exactly same object.
This article explains it in detail: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
BR
Michael
Both of the objects are created as a separate entities in the memory. To be precise, both of the objects are created as a separate entities on the heap (JavaScript engines use heap and stack memory models for managing running scripts). So, both of the objects may look the same (structure, properties etc.) but under the hood they have two separate addresses in the memory.
Here is some intuition for you. Imagine a new neighborhood where all houses are look the same. You've decided to build another two identical buildings and after finishing the construction both of the buildings are look the same and they even "sit" contiguously but still they are not the same building. They have two separate addresses.
I think that the simplest answer is "they are stored in different locations in memory". Although it is not always clear in languages that hide pointers ( if you know C, C++ or assembly language, you know what pointers are, if not, it is useful study to learn a low level language ) by making everything a pointer, each "object" is actually a pointer to a location in memory where the object exists. In some cases, two variables will point to the same location in memory. In others, they will point to different locations in memory that happen to have similar or identical content. It's like having two different URLs, each of which points to an identical page. The web pages are equal to each other, but the URLs are not.
I have a n*n*n array in javascript, in which i need to perform a LOT of access.
I don't need to access all elements sequentially, but at specific positions only. I also want, if possible, not to allocate all the memory of the array cells until it's used (other it would take several MB of memory directly).
I'm looking for the most efficient way to do so.
I tried to use a dictionnary indexed by a built key ( x + '#' + y + '#' + z ) but it's cleary not efficient enough.
Could you suggest some other efficient ways to achieve this ?
There's no faster way to access objects than a dictionary method, I'm afraid, because that's what everything in Javascript is, really. To not allocate the memory, you can use an object instead of an array:
var x = {};
var key = x + '#' + y + '#' + z;
x[key] = 'some value';
This will at least give you your memory concern, but I'm not sure it's really much of a concern. (Also, I'm not even sure that if you use an array it WILL allocate the memory, because I'm unfamiliar with memory allocation in Javascript).
I think your multidimensional array is perfectly fine. If created sparse, it will not eat up all the memory, and act more like a simple "dictionary" object - you could use nested objects as well. Yet, I'd propose that the nested lookup will be faster than in a huge dictionary, since the hash function gets simpler with less keys. Also, loading or iterating a full array from the innermost dimension will be noticably faster than querying each single item from the huge dictionary.
After all, if you don't actually experience any essential performance issues use what you find easier to write/read/use.
Does javascript use immutable or mutable strings? Do I need a "string builder"?
They are immutable. You cannot change a character within a string with something like var myString = "abbdef"; myString[2] = 'c'. The string manipulation methods such as trim, slice return new strings.
In the same way, if you have two references to the same string, modifying one doesn't affect the other
let a = b = "hello";
a = a + " world";
// b is not affected
However, I've always heard what Ash mentioned in his answer (that using Array.join is faster for concatenation) so I wanted to test out the different methods of concatenating strings and abstracting the fastest way into a StringBuilder. I wrote some tests to see if this is true (it isn't!).
This was what I believed would be the fastest way, though I kept thinking that adding a method call may make it slower...
function StringBuilder() {
this._array = [];
this._index = 0;
}
StringBuilder.prototype.append = function (str) {
this._array[this._index] = str;
this._index++;
}
StringBuilder.prototype.toString = function () {
return this._array.join('');
}
Here are performance speed tests. All three of them create a gigantic string made up of concatenating "Hello diggity dog" one hundred thousand times into an empty string.
I've created three types of tests
Using Array.push and Array.join
Using Array indexing to avoid Array.push, then using Array.join
Straight string concatenation
Then I created the same three tests by abstracting them into StringBuilderConcat, StringBuilderArrayPush and StringBuilderArrayIndex http://jsperf.com/string-concat-without-sringbuilder/5 Please go there and run tests so we can get a nice sample. Note that I fixed a small bug, so the data for the tests got wiped, I will update the table once there's enough performance data. Go to http://jsperf.com/string-concat-without-sringbuilder/5 for the old data table.
Here are some numbers (Latest update in Ma5rch 2018), if you don't want to follow the link. The number on each test is in 1000 operations/second (higher is better)
Browser
Index
Push
Concat
SBIndex
SBPush
SBConcat
Chrome 71.0.3578
988
1006
2902
963
1008
2902
Firefox 65
1979
1902
2197
1917
1873
1953
Edge
593
373
952
361
415
444
Exploder 11
655
532
761
537
567
387
Opera 58.0.3135
1135
1200
4357
1137
1188
4294
Findings
Nowadays, all evergreen browsers handle string concatenation well. Array.join only helps IE 11
Overall, Opera is fastest, 4 times as fast as Array.join
Firefox is second and Array.join is only slightly slower in FF but considerably slower (3x) in Chrome.
Chrome is third but string concat is 3 times faster than Array.join
Creating a StringBuilder seems to not affect perfomance too much.
Hope somebody else finds this useful
Different Test Case
Since #RoyTinker thought that my test was flawed, I created a new case that doesn't create a big string by concatenating the same string, it uses a different character for each iteration. String concatenation still seemed faster or just as fast. Let's get those tests running.
I suggest everybody should keep thinking of other ways to test this, and feel free to add new links to different test cases below.
http://jsperf.com/string-concat-without-sringbuilder/7
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
Just to clarify for simple minds like mine (from MDN):
Immutables are the objects whose state cannot be changed once the object is created.
String and Numbers are Immutable.
Immutable means that:
You can make a variable name point to a new value, but the previous value is still held in memory. Hence the need for garbage collection.
var immutableString = "Hello";
// In the above code, a new object with string value is created.
immutableString = immutableString + "World";
// We are now appending "World" to the existing value.
This looks like we're mutating the string 'immutableString', but we're not. Instead:
On appending the "immutableString" with a string value, following events occur:
Existing value of "immutableString" is retrieved
"World" is appended to the existing value of "immutableString"
The resultant value is then allocated to a new block of memory
"immutableString" object now points to the newly created memory space
Previously created memory space is now available for garbage collection.
Performance tip:
If you have to concatenate large strings, put the string parts into an array and use the Array.Join() method to get the overall string. This can be many times faster for concatenating a large number of strings.
There is no StringBuilder in JavaScript.
The string type value is immutable, but the String object, which is created by using the String() constructor, is mutable, because it is an object and you can add new properties to it.
> var str = new String("test")
undefined
> str
[String: 'test']
> str.newProp = "some value"
'some value'
> str
{ [String: 'test'] newProp: 'some value' }
Meanwhile, although you can add new properties, you can't change the already existing properties
A screenshot of a test in Chrome console
In conclusion,
1. all string type value (primitive type) is immutable.
2. The String object is mutable, but the string type value (primitive type) it contains is immutable.
Strings are immutable – they cannot change, we can only ever make new strings.
Example:
var str= "Immutable value"; // it is immutable
var other= statement.slice(2, 10); // new string
Regarding your question (in your comment to Ash's response) about the StringBuilder in ASP.NET Ajax the experts seem to disagree on this one.
Christian Wenz says in his book Programming ASP.NET AJAX (O'Reilly) that "this approach does not have any measurable effect on memory (in fact, the implementation seems to be a tick slower than the standard approach)."
On the other hand Gallo et al say in their book ASP.NET AJAX in Action (Manning) that "When the number of strings to concatenate is larger, the string builder becomes an essential object to avoid huge performance drops."
I guess you'd need to do your own benchmarking and results might differ between browsers, too. However, even if it doesn't improve performance it might still be considered "useful" for programmers who are used to coding with StringBuilders in languages like C# or Java.
It's a late post, but I didn't find a good book quote among the answers.
Here's a definite except from a reliable book:
Strings are immutable in ECMAScript, meaning that once they are created, their values cannot change. To change the string held by a variable, the original string must be destroyed and the variable filled with another string containing a new value...
—Professional JavaScript for Web Developers, 3rd Ed., p.43
Now, the answer which quotes Rhino book's excerpt is right about string immutability but wrong saying "Strings are assigned by reference, not by value." (probably they originally meant to put the words an opposite way).
The "reference/value" misconception is clarified in the "Professional JavaScript", chapter named "Primitive and Reference values":
The five primitive types...[are]: Undefined, Null, Boolean, Number, and String. These variables are said to be accessed by value, because you are manipulating the actual value stored in the variable.
—Professional JavaScript for Web Developers, 3rd Ed., p.85
that's opposed to objects:
When you manipulate an object, you’re really working on a reference to that object rather than the actual object itself. For this reason, such values are said to be accessed by reference.—Professional JavaScript for Web Developers, 3rd Ed., p.85
JavaScript strings are indeed immutable.
Strings in Javascript are immutable