51

It's not the setup to a joke, i'm really asking.

Douglas Crockford is fond of saying that in the javascript prototypal object-oriented language there is no need for new.

He explains that new was simply added to give people coming from class-based (i.e. "classical") object oriented programming languages some level of comfort:

JavaScript, We Hardly new Ya

JavaScript is a prototypal language, but it has a new operator that tries to make it look sort of like a classical language. That tends to confuse programmers, leading to some problematic programming patterns.

You never need to use new Object() in JavaScript. Use the object literal {} instead.

Okay, fine:

  • new bad
  • {} good

But then commenter Vítor De Araújo pointed out that the two are not the same. He gives an example showing that a string is not like an object:

A string object and a string value are not the same thing:

js> p = "Foo"
Foo
js> p.weight = 42
42
js> p.weight // Returns undefined

js> q = new String("Foo")
Foo
js> q.weight = 42
42
js> q.weight
42

The string value cannot have new properties. The same thing is valid for other types.

What is going on here that an string is not an object? Am i confusing javascript with some other languages, where everything is an object?

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • …and I do not totally agree with Crockford: it's not necessary to use `new Object` (neither is `new Array`, use `[]` instead), but if you want to define a new instance of a (pre)defined class, you really should use the `new` operator, like in `new Date()` or `new SchrodingersCat()`. – Marcel Korpel Oct 11 '10 at 16:00
  • @Marcel Korpel: *"should use"*, or **must** *use*? Is there any other way to construct a new object from the `Date` object prototype? – Ian Boyd Oct 20 '10 at 15:26
  • Good question, in case of `Date`: **must**. If you call `Date` as a bare function, it returns the current date and time as a string. Also see [Using constructor without operator 'new'](http://stackoverflow.com/questions/1928342/using-constructor-without-operator-new) and [Does Javascript's new operator do anything but make life difficult?](http://stackoverflow.com/questions/1744426/does-javascripts-new-operator-do-anything-but-make-life-difficult) – Marcel Korpel Oct 20 '10 at 15:40
  • @Marcel Korpel: Those links make things more confusing. What does `new Date` do? What does `new` do? Does javascript have constructors? How does one declare a constructor in javascript? How does one call a constructor in javascript? Does `new` call a constructor? – Ian Boyd Oct 21 '10 at 13:59
  • In short (just moved and don't have an internet connection at home): `new` creates a new object and calls the constructor function. `new Date` creates a new `Date` object set to the given time (instead of returning the current date/time as a string). For a better explanation I recommend you to read David Flanagan's *JavaScript: The Definitive Guide*. – Marcel Korpel Oct 23 '10 at 14:46
  • Class? what class? That is the whole point of a prototype OO system, is that there are no classes to use. – Jonathan Arkell Dec 02 '11 at 23:15
  • See also [Why are there two kinds of JavaScript strings?](http://stackoverflow.com/q/5514367/1048572) – Bergi Sep 17 '15 at 16:34

2 Answers2

103

"Everything is an object"... that's one of the big misconceptions that exist all around the language.

Not everything is an object, there are what we call primitive values, which are string, number, boolean, null, and undefined.

That's true, a string is a primitive value, but you can access all the methods inherited from String.prototype as if it were an object.

The property accessor operators (the dot and the bracket notation), temporarily convert the string value to a String object, for being able to access those methods, e.g.:

"ab".charAt(1); // "b"

What happens behind the scenes is something like this:

new String("ab").charAt(1); // "b", temporal conversion ToObject

As with the other primitive values, such as Boolean, and Number, there are object wrappers, which are simply objects that contain the primitive value, as in your example:

var strObj = new String("");
strObj.prop = "foo";

typeof strObj; // "object"
typeof strObj.prop; // "string"

While with a primitive:

var strValue = "";
strValue.prop = "foo";

typeof strValue; // "string"
typeof strValue.prop; // "undefined"

And this happens because again, the property accessor on the second line above, creates a new temporal object, as:

var strValue = "";
new String(strValue).prop = "foo"; // a new object which is discarded
//...
ajorquera
  • 1,297
  • 22
  • 29
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 1
    I prefer to not use uppercase with primitives, like `boolean` and `number`, to avoid confusion with the object wrappers `Boolean` and `Number` (but the ECMAScript specification does not do so). Also, `NaN` is a primitive value, too. – Marcel Korpel Oct 11 '10 at 15:48
  • Marcel, yeah, object wrappers can cause confusion, e.g. `if (new Boolean(false)) {alert(':D');}`. Yes, `NaN`, positive and negative `Infinity` are values of the [Number type](http://ecma262-5.com/ELS5_HTML.htm#Section_8.5). – Christian C. Salvadó Oct 11 '10 at 15:55
  • 1
    Ah, yes, `Infinity`, I already thought I forgot some other value. How can one ever forget `Infinity`? – Marcel Korpel Oct 11 '10 at 15:57
  • 3
    I want to stress that when using object methods to primitive values, the variable is only *temporarily* converted to an object and after the proposed operation, the object is converted back to a primitive. This concept can cause confusion, as you can see in [String object versus literal - modifying the prototype?](http://stackoverflow.com/q/3756549/258127) – Marcel Korpel Oct 11 '10 at 16:05
  • 1
    Even after two years this answer remains effective! +1!! – MD Sayem Ahmed Nov 21 '12 at 07:16
  • Yes! Thank you CMS. +1 for great answer AND being the first time I have ever seen the ECMA specs linked! (bookmarked!) – Todd Vance Jul 31 '13 at 14:18
  • @CMS is this still valid ? or do the primitives themselves start as fully fledged objects in the latest JS implementations. It seems expensive to convert the primitives behind the scenes every time you invoke a method on them to an Object, and for almost every other operation. This is especially true in Python, where **everything** starts as an object, not converted on the fly or at a later time, so for instance the number `3` is an instance of `int` (talking about Python now), where that instance holds both the value and the methods. – Marius Mucenicu Sep 19 '19 at 06:28
  • @MariusMucenicu, this holds true, but in a practical sense, I'm pretty sure the JS engines have optimized and inlined the access of prototype members on primitive values. – Christian C. Salvadó Sep 26 '19 at 16:36
4

The most important difference between a string and an object is that objects must follow this rule for the == operator:

An expression comparing Objects is only true if the operands reference the same Object.

So, whereas strings have a convenient == that compares the value, you're out of luck when it comes to making any other immutable object type behave like a value type. (There may be other differences too, but this is the only one that causes JavaScript developers excitement on a daily basis). Examples:

"hello" == "hello"
-> true
new String("hello") == new String("hello") // beware!
-> false
personal_cloud
  • 3,943
  • 3
  • 28
  • 38
  • this is the wrong comparison, these are clearly 2 different objects, so to compare the strings, you need to compare the values of `new String("hello").valueOf()` – MichaelHabib Oct 13 '20 at 03:15
  • 1
    @MichaelHabib It is the right comparison to demonstrate that comparing two objects compares the reference. Of course, you can convert the `String` object back to a `string` and compare it as a value. But the question is about how objects behave differently from strings. (Not about how to compare the values of objects). – personal_cloud May 12 '22 at 06:41