Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between string primitives and String objects in JavaScript?

People also ask

What is string primitives?

In JavaScript, a primitive (primitive value, primitive data type) is data that is not an object and has no methods or properties. There are 7 primitive data types: string.

Is string object or primitive?

String is an object, in android or java it isn't a primitive type at all. you can use strings to store in SharedPreferences.

What is string object in JavaScript?

The String object lets you work with a series of characters; it wraps Javascript's string primitive data type with a number of helper methods. As JavaScript automatically converts between string primitives and String objects, you can call any of the helper methods of the String object on a string primitive.

Is a string literal a primitive?

String literals are not primitive values. They are a shorthand notation for representing String objects. Strings consist of characters enclosed by double quotes ("). The character escape codes can be used within String literals to represent special characters within the string.


JavaScript has two main type categories, primitives and objects.

var s = 'test';
var ss = new String('test');

The single quote/double quote patterns are identical in terms of functionality. That aside, the behaviour you are trying to name is called auto-boxing. So what actually happens is that a primitive is converted to its wrapper type when a method of the wrapper type is invoked. Put simple:

var s = 'test';

Is a primitive data type. It has no methods, it is nothing more than a pointer to a raw data memory reference, which explains the much faster random access speed.

So what happens when you do s.charAt(i) for instance?

Since s is not an instance of String, JavaScript will auto-box s, which has typeof string to its wrapper type, String, with typeof object or more precisely s.valueOf(s).prototype.toString.call = [object String].

The auto-boxing behaviour casts s back and forth to its wrapper type as needed, but the standard operations are incredibly fast since you are dealing with a simpler data type. However auto-boxing and Object.prototype.valueOf have different effects.

If you want to force the auto-boxing or to cast a primitive to its wrapper type, you can use Object.prototype.valueOf, but the behaviour is different. Based on a wide variety of test scenarios auto-boxing only applies the 'required' methods, without altering the primitive nature of the variable. Which is why you get better speed.


This is rather implementation-dependent, but I'll take a shot. I'll exemplify with V8 but I assume other engines use similar approaches.

A string primitive is parsed to a v8::String object. Hence, methods can be invoked directly on it as mentioned by jfriend00.

A String object, in the other hand, is parsed to a v8::StringObject which extends Object and, apart from being a full fledged object, serves as a wrapper for v8::String.

Now it is only logical, a call to new String('').method() has to unbox this v8::StringObject's v8::String before executing the method, hence it is slower.


In many other languages, primitive values do not have methods.

The way MDN puts it seems to be the simplest way to explain how primitives' auto-boxing works (as also mentioned in flav's answer), that is, how JavaScript's primitive-y values can invoke methods.

However, a smart engine will not convert a string primitive-y to String object every time you need to call a method. This is also informatively mentioned in the Annotated ES5 spec. with regard to resolving properties (and "methods"¹) of primitive values:

NOTE The object that may be created in step 1 is not accessible outside of the above method. An implementation might choose to avoid the actual creation of the object. [...]

At very low level, Strings are most often implemented as immutable scalar values. Example wrapper structure:

StringObject > String (> ...) > char[]

The more far you're from the primitive, the longer it will take to get to it. In practice, String primitives are much more frequent than StringObjects, hence it is not a surprise for engines to add methods to the String primitives' corresponding (interpreted) objects' Class instead of converting back and forth between String and StringObject as MDN's explanation suggests.


¹ In JavaScript, "method" is just a naming convention for a property which resolves to a value of type function.


In case of string literal we cannot assign properties

var x = "hello" ;
x.y = "world";
console.log(x.y); // this will print undefined

Whereas in case of String Object we can assign properties

var x = new String("hello");
x.y = "world";
console.log(x.y); // this will print world

String Literal:

String literals are immutable, which means, once they are created, their state can't be changed, which also makes them thread safe.

var a = 's';
var b = 's';

a==b result will be 'true' both string refer's same object.

String Object:

Here, two different objects are created, and they have different references:

var a = new String("s");
var b = new String("s");

a==b result will be false, because they have different references.