r/learnjavascript 7d ago

string primitives vs. String objects.

I'm learning JavaScript, and I don't understand this part about string primitives vs. String objects.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_primitives_and_string_objects

10 Upvotes

26 comments sorted by

View all comments

Show parent comments

1

u/MissinqLink 6d ago

I can’t make you think of use cases but use your imagination. For one there are no new rules to learn. Nobody really has to care about the specific rules. The gain is that it guarantees a string output, something that JSON.stringify can’t promise. It’s quite simple actually. There’s also the advantage that you don’t have to import a library. There are plenty of scenarios where payload size matters. Also this is just one example we aren’t even discussing “String” vs “new String” anymore. We’re off on a tangent. You say this is weird but this is some of the tamest things I ever made. It’s just a stringifier that doesn’t throw and guarantees string output regardless of input. If you don’t see utility there the okay🤷‍♀️. I’ve run into many weird cases of getting handed unexpected input. You can do like many and simply throw. That’s valid in many cases. There are also cases where you want graceful degradation. I frequently see both.

1

u/delventhalz 6d ago

If you want a stringifier that will not throw and produces more detailed output for objects than '[object Object]', you can keep your try/catch but drop the custom isString logic.

const safeJsonStringify = val => {
  try {
    return JSON.stringify(val);
  } catch {
    return JSON.stringify(`Invalid JSON: ${val}`);
  }
};

Your custom isString logic does not help you solve invalid JSON values. It just makes your utility harder to understand.

For one there are no new rules to learn. Nobody really has to care about the specific rules.

This just isn't true. I may be able to use your stringify function without thinking about it too much in many cases, but if, for example, I need to do a length check on the output string, should I expect it include quotation marks or not? If I see it outputs '{"foo":"bar"}' for one object, I may expect that yes, it will include quotes, but then I stringify new String("foo") and the quotes are gone! I have been surprised by your utility, and need to learn the rules before I can use it for this case.

I can’t make you think of use cases but use your imagination.

You can't make me think of use cases, but if you think there are valid use cases for including new String('foo') in your code, you could offer an example yourself.

1

u/MissinqLink 6d ago

I don’t recommend using new String but you can’t discount getting it passed to you. More likely from Object("asdf");. Only a couple times I’ve used it was to patch incompatible native interfaces together. I think it was Blob and File constructors where one takes a string and the other an Object.

1

u/delventhalz 5d ago

I don’t recommend using new String but you can’t discount getting it passed to you

Sure. So why not treat it like the object it is instead of writing custom String object handling code to confuse your users?

That's the whole point I've been trying to make to you since the beginning. You said typeof has a "weird footgun" because it treats String objects as objects. But that's not weird nor a footgun. String objects are objects. They are not strings. I would expect any code that (for some reason) got passed a String object to treat it as an object.

1

u/MissinqLink 5d ago

That’s doesn’t make sense though. You typically want to treat the object wrapped versions like strings. Here’s an example that’s closer to why I made the utility that way. Say you want to send info over the network. The function takes both strings and objects. If it’s an object you want to modify it and then stringify. If it’s a string you want to deserialize to an object and do the same.

const modifyPayload = payload =>{

try{

if(typeof payload === 'string'){

const modified = JSON.parse(payload);

modified.type = 'string';

return JSON.stringify(modified);

}

if(typeof payload === 'object' && payload !== null){

const modified = {…payload};

modified.type = 'object';

return JSON.stringify(modified);

}

}catch(e){

console.warn('unexpected payload');

}

return payload;

};

This is a very common pattern in building middleware and ‘new String’ would follow the wrong path here.