Why are Strings JavaScript Primitives? [duplicate] - javascript

MDN states:
primitive, primitive value
A data that is not an object and does
not have any methods. JavaScript has 5
primitive datatypes: string, number,
boolean, null, undefined. With the
exception of null and undefined, all
primitives values have object
equivalents which wrap around the
primitive values, e.g. a String object
wraps around a string primitive. All
primitives are immutable.
So when we call a "s".replace or "s".anything is it equivalent to new String("s").replace and new String("s").anything?

No, string primitives do not have methods. As with numeric primitives, the JavaScript runtime will promote them to full-blown "String" objects when called upon to do so by constructs like:
var space = "hello there".indexOf(" ");
In some languages (well, Java in particular, but I think the term is in common use) it's said that the language "boxes" the primitives in their object wrappers when appropriate. With numbers it's a little more complicated due to the vagaries of the token grammar; you can't just say
var foo = 27.toLocaleString();
because the "." won't be interpreted the way you'd need it to be; however:
var foo = (27).toLocaleString();
works fine. With string primitives — and booleans, for that matter — the grammar isn't ambiguous, so for example:
var foo = true.toString();
will work.

The technically correct answer is "no".
The real-world answer is "no, but it will work anyway". That's because when you do something like
"s".replace()
the interpreter knows that you want to actually operate on the string as if you had created it with
var str = new String("s")
and therefore acts as if you had done that.

Related

Why does JavaScript have boxed versions of primitives?

Why does JavaScript have boxed versions of primitives?
Like, I'm good with true and false, why do I need
new Boolean(true) === new Boolean(true) // false
I get that languages like Java and Objective-C had the boxed things because you couldn't put primitives into the same data structures as non-primitives. But JS always allowed arrays of mixed things [1, 2, {}, ""] and anything could be the value for a key in an object.
I'm not asking for a justification: of course capital "B" Boolean is nonsense. But I'm genuinely curious about how this happened. There must have been a reason at the time.
JavaScript has boxed primitive types so that their instances can inherit properties (especially methods) from their prototypes, which fits in well with the auto-boxing of the receiver value on property access (and method calls).
For example
Boolean.prototype.demo = "!";
console.log(true.demo);
console.log(true.toString());
Contrast this to undefined.toString(), which is not auto-boxed.
This reason is confirmed by the creator of the language:
the so-called primitive types Boolean, Number, and String each have a
corresponding Object subtype: Boolean, Number, and String
respectively. When a primitive value is used as an object, it is
automatically “boxed” or wrapped by a new instance of the
corresponding object subtype. When used in an appropriate primitive
type context, the box/wrapper converts back to the primitive value.
However, he actually was rather unhappy with that, and wanted to change the type system for ES4 (which, we all known, never happened).
The question could actually even have been framed the other way round: "Why does JavaScript have primitive types when it already has Boolean, Number and String objects?". They really aren't necessary at all, many languages do fine without them and just live the object-oriented everything is an object maxim - including languages that were the inspirations for JS.
Again, we learn from Brendan Eich:
The diktat from upper engineering management was that the language must
“look like Java”. […]
I’m not proud, but I’m happy that I chose Scheme-ish first-class
functions and Self-ish (albeit singular) prototypes as the main
ingredients. The Java influences, especially y2k Date bugs but also
the primitive vs. object distinction (e.g., string vs. String), were
unfortunate.

JavaScript object meaning

I'm currently doing a bit of JavaScript and I have some troubles trying to explain myself one thing.
If I do that :
var text = new String("Enter any value here");
We all agree that "text" is an object, right?
But what should be "String" called then? Because I see everywhere that String is also an object, but wouldn't it be simpler to call it a class like in PhP.
Is there an other name, more precise than just object for String?
If someone can explain me the subtlety, I would be very happy. Thank you!
I think the source of your confusion is unfamiliarity with Prototypal Inheritance model. I suppose you are well versed with 'Classical Model' where classes are constructed using Classes as blueprint. On the other hand in JavaScript other Objects are created using an Object as a prototype or using an empty object and then pinning new properties in it.
If you try logging typeof(String) you will get output as function. Here when we do a new String('hello, world'), we get a new String object Hello, World. Thus String is a constructor in JavaScript.
By design, JavaScript (the implementation of the ECMAScript standard) has no class. So String cannot ever be called a class.
String here is but an object, just as almost everything in JavaScript is (as some the answers have already stated).
console.log(String instanceof Object); // true
Actually a special object: a function.
console.log(typeof String); // "function"
console.log(String instanceof Function); // true
And even a special function: a function that should be called as a constructor, hence the capital 'S'.
Even more special function: it is a built-in function (it is "present in the language" and therefore provided by the host environment -the browser or node, for example).
This special function allows you to instantiate an object of type String:
var aString = new String("A string");
But this is the wrong way to do it: you should write this:
var aPrimitiveString = "A string";
which interestingly, by the way, doesn't make text a String (Object), but a string (primitive).
console.log(typeof(aString)); // "object"
console.log(aString instanceof String); // true
console.log(aString instanceof Object); // true
console.log(typeof(aPrimitiveString)); // "string"
console.log(aPrimitiveString instanceof String); // false
console.log(aPrimitiveString instanceof Object); // false
Even in ECMAScript 6 (AKA ES6, AKA Harmony, AKA ES2016), there won't be any classes in the acception you have of it, "classes" in ES6 will still be an object, of type function, with prototypal inheritance.
One more thing: String can also be used to explicitly coerce a value into a string primitive:
var number = 1;
var numberAsString = String(1);
console.log(number); // 1
console.log(numberAsString); // "1"
console.log(typeof number); // "number"
console.log(typeof numberAsString); "string"
for the sake of completeness, I hope you guessed that:
number is a primitive number
numberAsString is a primitive string
new number(1) would be an object, instance of Number and Object
Number('0') would be a primitive number
same goes for Boolean
There are no classes in JavaScript, there won't ever be (I don't want any of it, anyway), that is what make the language so flexible, expressive and powerful.
Maybe you would want to take a look at this: http://javascript.crockford.com/inheritance.html (and the whole site and work of Douglas Crockford).
JavaScript is an object oriented language without classes.
However, you can apply many object oriented paradigms in JavaScript. It has its own mechanisms to do so.
In JavaScript, instead of classes you use objects. That's really about it already. You can think of String as a class if you want, but sometimes it can lead to confusion, because it is easy to confuse concepts known from Java or C++ with JavaScript. The implementation is just different.
I suggest you omit to think of it as a class, and call it an object. And try not to apply terminology of other languages like PHP with JavaScript.
Now, the confusion might be that in other OO languages you define a class and then you create instances from that class, which we refer to as objects.
In JavaScript you simply create a new copy of another object.
Please refer to this link and...
...note that JavaScript distinguishes between String objects and
primitive string values. (The same is true of Boolean and Numbers.)
According to w3schools:
In JavaScript, almost "everything" is an object.
Booleans can be objects (or primitive data treated as objects)
Numbers can be objects (or primitive data treated as objects)
Strings can be objects (or primitive data treated as objects)
Dates are always objects
Maths are always objects
Regular expressions are always objects
Arrays are always objects
Functions are always objects
Objects are objects
In JavaScript, all values, except primitive values, are objects.
Primitive values are: strings ("John Doe"), numbers (3.14), true,
false, null, and undefined.
MDN says in javascript everything are objects.
In JavaScript, almost everything is an object. All primitive types
except null and undefined are treated as objects. They can be assigned
properties (assigned properties of some types are not persistent), and
they have all characteristics of objects.
Creating new objects
JavaScript has a number of predefined objects. In addition, you can
create your own objects. You can create an object using an object
initializer. Alternatively, you can first create a constructor
function and then instantiate an object using that function and the
new operator.
So in javascript the idea of class doesn't really exist like in other languages. It's just an instantiated object or function if you prefer.
typeof 1.00 // number
typeof 1 //number
typeof "string" //string
typeof String("string") //string
typeof new String("string") //object
typeof {} //object
typeof [] //object
Demo
It seems possible to create classes in ECMAScript 6
It is said that:
Defining classes
Classes are in fact functions, and just like you can define function
expressions and function declarations, the class syntax has the two
opponents:
class expressions and class declarations.

Do any standard JavaScript APIs or libraries return strings as String objects?

Until recently, I didn't realise that there are two types of strings (and bools, and numbers) in JavaScript: primitives such as "blah", and objects such as new String("blah").
They differ in very "gotcha"-prone ways, the biggest one of which seems to be the different typeof value ("string" vs "object"), but a number of other differences exist, some documented at MDN.
There's no point in creating String objects because the primitive strings work just as well, and JSHint even treats this as an error. So I'd really like to pretend String instances don't even exist, and only support primitive strings in my code.
This makes me wonder: can I get a surprise String instance by calling some standard API that returns a string? Or is it really safe to assume that unless someone screws up by explicitly writing new String, I will never see one of these?
This github search shows that some people are using new String.
And this answer has a nice explanation for String obj:
No native JavaScript object, major library or DOM method that returns
a string will return a String object rather than a string value.
However, if you want to be absolutely sure you have a string value
rather than a String object, you can convert it as follows:
var str = new String("foo");
str = "" + str;
I am not aware of any convention to only use primitive strings. There is also an ever growing amount of API's available, and I'm pretty sure every now and then someone will pull the constructor trick. I would like to give some debugging advice on how to spot this quicky, but I think the typeof check is the only obvious way to quicky note the difference.
You could use a check like this answer, although I think it is not worth the trouble:
function isString(string){
return typeof myVar == 'string' || myVar instanceof String;
};
isString("foo"); //returns true
isString(new String("bar")); //returns true
isString({}); //returns false;
Conclusion: I'm afraid you just have to pray that you don't encounter
these quirky corner cases.

Everything is an object?

At one popular blog, the author asked his audience what was their “Ah ha!” moment for JavaScript and most of the people said that it was realizing that everything in JavaScript is an object.
But being new to JS and programming in general I don't quite get what that means. It doesn't seam like it's related to actual JS Object - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
Or it does?
If it doesn't could you please explain what do they mean by "everything in JavaScript is an object".
Or it's all about OO Programming in general and reading something on this subject will help to understand it? Can you recommend what to read on this topic?
Go back to first principles.
What's an object? It's a software component that encapsulates state and behavior together into a single entity in memory.
By that definition, you can see where everything can be thought of as an object. Functional programmers make functions first class objects. Data folks would say that data, even that without behavior, can be thought of as an object (albeit not a very smart one).
I don't see what this changes.
JavaScript treats functions as objects.
I'm not sure what effect this insight will have on your programming.
What they mean, most likely, is that any data that can be assigned to a variable has properties (and therefore methods) that can be accessed in an object like fashion.
// strings
"asdf".length; // 4
"asdf".replace('f', 'zxc'); // "azxc"
// numbers
(10).toFixed(2); // "10.00"
// booleans
true.someProp; // undefined (point is it doesn't crash)
They even have prototypes they inherit from.
"omg".constructor; // function String() { [native code] }
String.prototype.snazzify = function() {
return "*!*!*" + this + "*!*!*";
};
"omg".snazzify(); // "*!*!*omg*!*!*"
However, these are primitives, and while they behave object like in a lot of ways, they are different from other "real" JS objects in a few ways. The biggest of which is that they are immutable.
var s = "qwerty";
s.foo; // undefined, but does not crash
s.foo = 'some val'; // try to add a property to the string
s.foo; // still undefined, you cannot modify a primitive
Do note though that functions are real mutable objects.
var fn = function(){};
fn.foo; // undefined
fn.foo = 'some val'; // try to add a property to the function
fn.foo; // "some val"
So while it's not technically true that "everything in JS is an object", under most circumstances you can treat them mostly like objects in that they have properties and methods, and can potentially be extended. Just be sure you understand the caveats.
NOT everything in JavaScript is an object.
All data in JavaScript must fall into one of six primitive types, or the object type. Primitive types includes boolean, null, undefined, string, number and symbol; everything that is not a primitive is an object.
This means functions are objects, arrays are objects, ES6 classes de-sugars into a function which are objects.
The confusion arises because primitive values have object wrappers. When you try to access the length property on the string literal, JavaScript creates a temporary object wrapper around the primitive and access the length property of that object wrapper. After the property has been retrieved, the object wrapper is discarded. This is known as autoboxing.
Essentially, it is implemented similar to the following:
const foo = "bar";
// When you run `foo.length`, it's similar to
tmp = String(foo);
tmp.length;
delete tmp;
Or
const foo = "bar";
(new String(foo)).length;
The string, number and boolean primitives have object wrappers, but null and undefined do not. So trying to access a property or method from those primitives would throw an error.
null.length; // Uncaught TypeError: Cannot read property 'length' of null
undefined.length; // Uncaught TypeError: Cannot read property 'length' of undefined
Not everything is an object in JavaScript. For example a number is not an object.
Different languages have different definition of "object". For JavaScript, the official definitions can be found in the ECMAScript Language Specification, which states:
In ECMAScript, an object is a collection of zero or more properties
each with attributes that determine how each property can be used (...) Properties are containers that hold other objects,
primitive values, or functions. A primitive value is a member of one
of the following built-in types: Undefined, Null, Boolean, Number,
BigInt, String, and Symbol; an object is a member of the built-in type
Object; and a function is a callable object.
So by this definition it is clear that primitive values (like numbers) are not objects. Even strings are not objects, which is different from most other OO languages.
So why do some people say "everything is an object"? You have to ask them! But I suspect it is because they are getting confused by the built-in objects Number, Boolean, String etc. which can be used as wrappers around the corresponding primitive values. This wrapping sometimes happen automatically, which can make primitive values look like object and for example allow you to (seemingly) access properties on primitives. But in reality the properties are on the wrapper object.
'ALMOST everything is an object' because the MAIN code-units are JS-objects. On primitives you can NOT add members for example as on all objects. My answer why JS-functions are JS-objects here: https://stackoverflow.com/a/24811539

How is the variable sized JavaScript string a primitive type?

From what I understand, the (basic) string type in JavaScript is a primitive type, meaning its variables are allocated on the stack.
I would have thought that for a type to be allocatable on the stack, it needed to have a fixed size -- something which presumably holds true for the other primitive types like boolean, number, etc.
Am I somehow wrong to assume that, or is some other internal magic used to make strings in JavaScript primitive types?
EDIT:
This gets more complicated when one considers that JavaScript is loosely typed. Which makes me wonder how any local variable can be allocated on the stack.... given that the size of what might be assigned to it during the course of a function is not fixed.
But I guess (a perhaps simplified) answer to this might be that all local variables could be assigned a fixed maximum size on the stack. Say this is 8 bytes which I think is the size of the number type, and should be large enough to accommodate all the other primitive types (except the string) as well as memory addresses (for when a local variable is assigned a reference type). But, surely strings cannot be limited to 8 bytes (or any size for that matter). Which makes me conclude that strings (even the primitive type ones) are not (cannot be) assigned on the stack. And hence the term "Primitive type" in JavaScript is used to mean a "basic/building block" type, rather than one which is necessarily allocated on the stack (contradicting what I have read in numerous sources including the book "Professional JavaScript..." by Nicholas Zakas).
Anyone have any other take or a pointer to a good source talking about this?
A string is a both an object and a primitive.
When doing:
var s = "this is a string";
you actually do:
var s = new string("this is a string");
behind the curtains.
The first being a primitive array with characters, on which the second one refers.
Strings are immutable, meaning they can't be changed. If you try to change it (i.e. reverse it), you will create a new string primitive, on which the object reference will point to.
The storage used to represent variables in the Javascript interpreter need not look anything like a stack - it's implementation dependent.
Strings aren't allocated on the stack
where a variable is allocated doesn't distinguish primitives from objects
Strings aren't primitives, they are of the class "string"
The difference between a primitive and a type is that types have methods and you can assign new properties to them:
var a = 1, b = {}, s = '';
a.foo = 1; // doesn't work, but no error either
b.foo = 1; // works
s.foo = 1; // doesn't work, but no error either
console.log(a.foo);
console.log(b.foo);
console.log(s.foo);
​
gives
undefined
1
undefined
So all in all, I'm not sure that using "primitive" makes sense in JavaScript since the line is blurred.
A string is a "value object" which means you can't change any of the properties. For example, when you replace characters in a string, you get a new string; the old string doesn't change.

Categories

Resources