2

How does JS interpreter this line: if ("foo"[0] === "f"){}? Two versions I could think of:

Version 1:

JavaScript creates a completely new string object which stores "f". This would require a lot more time than the second option, tho in my opinion this version looks more like JavaScript than the other.

Version 2:

Either JavaScript's lexer or parser converts "foo"[0] to "f". Because we are not talking about initializing or setting the value of a variable, we don't need to store the whole string, and we don't need to create a new string object. The interpreter just simply runs if ("f" === "f") {} .

Which of the 2 versions are the correct one? Is there another version? I'm also happy to read the solutions in other languages.

Wrench56
  • 290
  • 2
  • 14
  • @bravo Yes I know both could be right and I know every single engine can be different. Also it does not affect my project. I'm just curious, I'm a newbie in JS but I have some experience in other programming languages. I was just wondering if there is a default version for the various engines. I don't think they changed this every time they made a new engine. Tho it is possible that this isn't the case. – Wrench56 Aug 03 '21 at 01:09
  • I'll remove my comment, I just thought you were worrying about micro optimisations (or nano optimisations) that really have no real world impact for 99.999% of projects – Bravo Aug 03 '21 at 01:11
  • @Roko C. Buljan Thanks for the link! Be careful Strung.prototype.charAt() requires the string to be an object. So when you use .charAt() the string is instantly converted in an object. With "foo"[0] the lexer or parser can convert that to simply "f" – Wrench56 Aug 03 '21 at 01:12
  • Does this answer your question? [Do common JavaScript implementations use string interning?](https://stackoverflow.com/questions/5276915/do-common-javascript-implementations-use-string-interning) – smac89 Aug 03 '21 at 01:13
  • @Bravo No need to remove it, I know this is a "dumb" question. It's just hard to disassamble JavaScript so before my curiousity wins and I spend hours figuring out disassambled JS, I try to get an answer here ;) – Wrench56 Aug 03 '21 at 01:15
  • @Wrench56 - I didn't say it was dumb, there's no such thing as a dumb question - since you know that there is no correct answer as it is down to the engines implementation, I removed my comment as it has no value :p – Bravo Aug 03 '21 at 01:17
  • 1
    @Roko C. Buljan .charAt() is a method of the string object in js. String is not a primitive! .charAt() is only possible, when the string is an object – Wrench56 Aug 03 '21 at 01:17
  • @Roko C. Buljan Well in your case it's not so obvious. "Wrench56".charAt(0); means that "Wrench56" is an object. With "Wrench56"[0] the parser could recognise that as "W". Tho the interpretation depends on the context too! – Wrench56 Aug 03 '21 at 01:22
  • 1
    You forgot the third option where the interpreter recognizes a static expression and simply replaces it with its value. In this case, true or false. Also as I mentioned with the flagged question, there is also the option that the string is interned, and is not recreated each time the expression is evaluated – smac89 Aug 03 '21 at 01:22
  • @smac89 Thanks for the answer! The thing is if it recognizes a static expression at some point it has to recognize "foo"[0]. The question is how? – Wrench56 Aug 03 '21 at 01:28
  • Given your concerns (engine implementation of String primitives vs String object) I thik this might be a duplicate of https://stackoverflow.com/q/17256182/383904 – Roko C. Buljan Aug 03 '21 at 01:34
  • @smac89 to reply 1: Yes, JS might use string interning but still at some point it has to convert "foo"[0] to "f" before creating an ``intern `` – Wrench56 Aug 03 '21 at 01:34
  • @RokoC.Buljan Not exactly a duplicate: My question is not : "What's the difference between string primitive and string object". My question is: "How is "foo"[0] interpretered". That's not the same: The thread there did not talk about the interpretation of "foo"[0]. They only talked about .charAt() which requires a string object, so JS converts it to a string object before running .charAt(). In my case we do not need to convert "foo" to an object. Giving an index does not convert "foo" to an object. (Or at least it should not). It should return the first byte of "foo" which is "f". – Wrench56 Aug 03 '21 at 01:43
  • JavaScript automatically converts primitives to String objects. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_primitives_and_string_objects By doing so you can use Methods on *primitive* Strings. `Object.getPrototypeOf("f"[0]); // String` << from primitive, being 2 or 5 bytes in memory address. Implementation wise - as suggested might be worth taking a look in the V8's C++ code to get more clues on that specific engine. – Roko C. Buljan Aug 03 '21 at 01:47
  • @RokoC.Buljan The doc says that it only converts primitives to String objects when you try to use a method on them. Also note, that in my case we do not save anything, we just have to check if 2 letters are the same. We don't really need the "foo" string, only the "f". So in assembly the only used char would be "f" (and the other letter in my case "f"). – Wrench56 Aug 03 '21 at 01:52
  • @RokoC.Buljan I'll read v8::String and see whatsup. – Wrench56 Aug 03 '21 at 02:28
  • 1
    [class String : public Primitive - Line 1018](https://v8docs.nodesource.com/node-0.8/d4/da0/v8_8h_source.html) you can find the hups and hops - Also refer to `StringObject` in the same file. – Roko C. Buljan Aug 03 '21 at 02:31

0 Answers0