2

According to Is JavaScript a pass-by-reference or pass-by-value language? JavaScript passes string objects by value. Because of that, calling the indexOf method will trigger copying the content.

In my case, I am parsing a big string to look for data. I heavily use indexOf to find data. String can big as long as 100-200KB and I could need to call indexOf up to 1000 times per full scan.

I'm afraid this will cause polluting 'memory' with unnecessarily copied string and could impact performance.

Am I correct in my conclusion? If so, what is the proper way to deal with my task?

Potentially, I could use regular expressions, but at the moment that looks too complex.

Community
  • 1
  • 1
Budda
  • 18,015
  • 33
  • 124
  • 206
  • 2
    The nature of string primitive values is weird in JavaScript. I do not think it's accurate to assume that a copy of all the bytes in a string primitive are copied when a string is passed to a function. Because string primitives are immutable, representing those values (internally) as object references works perfectly well. They *behave* like primitives, but they're *implemented* like objects. – Pointy Apr 24 '15 at 03:44
  • js strings are by reference. just use indexOf and see how it performs. optimize later, if necessary – Cory Danielson Apr 24 '15 at 04:51
  • 1
    Did your question get answered? If so, please select one of the answers. If not, please describe what is missing from the answers. – jfriend00 Apr 28 '15 at 04:40

2 Answers2

2

Strings are a strange beast in Javascript, they seem to inhabit a middle ground between primitive types and objects. While technically they're considered primitive, they can in many circumstances be treated as if they were a reference, due to their immutability.

Given that they are immutable, I'd be very surprised if a copy of the string was passed to any function, since that would be both hideously expensive and totally unnecessary.

A seemingly easy way to find out would be to pass a string to a function and change one of its characters to see if that's reflected in the original string on return. However, as mentioned, the immutability of strings makes that impossible.


It may be possible to test this in an indirect manner by executing indexOf("a") against one of two string in a loop of many million times.

The string to search would either be "a" or "a very long string containing many thousands of characters ...".

If the strings are passed by reference, there should be no noticeable difference in the times. Passing by value should be detectable since you have to copy the string millions of times and a short string should copy faster than a long one.

But, as I said, it's probably unnecessary since the engine will most likely be as optimised as possible.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
1

.indexOf() is merely a search of the string and just returns a numeric index into the string. There is no need to make a copy and no copy is made. This doesn't really have anything to do with value/reference in Javascript. The operation is merely a search that returns an index. There is simply no need to make a copy.

Strings in Javascript are immutable. That means they can never be changed and these indexes into the string always point at the same place in the string. Any operation that operates on a string to make a change, returns a new string leaving the old one.

This allows for some interesting optimizations in the implementation. Because a string is immutable, it can be shared among all points of code that have a reference to it. Whenever anyone calls a function to modify the string, it simply returns a new string object created from the old one plus the modification.

If you were to use the index from .indexOf() with .slice() or something like that, then you would be copying part of the original string into a new string object (likely using some additional memory).

If you want to test this for yourself, feel free to run as many .indexOf() operations as you want on a large string and watch memory usage.

jfriend00
  • 683,504
  • 96
  • 985
  • 979