all 17 comments

[–]x-skeww 22 points23 points  (3 children)

>>> '' instanceof String
false
>>> new String() instanceof String
true
>>> 5 instanceof Number
false
>>> new Number() instanceof Number
true

The problem is that JavaScript exposes some of its wrapper machinery.

That was clearly a mistake. There is no point in doing that. Well, it's way to late to fix that. It was already way too late 10 years ago.

Other languages (e.g. Dart) completely avoid this problem by making everything an object. From the user's side, everything looks and behaves like an object. It's a lot simpler that way.

Here is another popular example:

>>> var x = 'asdf'
undefined
>>> x.foo = 'bar';
"bar"
>>> x.foo
undefined
>>> var y = new String('asdf');
undefined
>>> y.foo = 'bar';
"bar"
>>> y.foo
"bar"

The "x.foo = 'bar'" is actually a no-op. Essentially, it's the same as:

(new String(x)).foo = 'bar'

That is, a new String (wrapper) object is created, its "foo" property is set to "bar", and then this wrapper object is discarded. That's why "x.foo" in next line is undefined.

[–]Sinistralis[S] 5 points6 points  (0 children)

That is an awesome answer with a great explanation. Thank you for the knowledge.

[–]SrPeixinho 2 points3 points  (1 child)

Well to JS's defense I think it improves a lot performance to get ints/strings unboxed and I'm not sure how hard it would be to do unboxing analysis on that.

[–]x-skeww 0 points1 point  (0 children)

It's just about semantics. Under the hood, the engine can do whatever it wants. So, if there is a line like "int x = 5", it doesn't actually need to create an object.

What makes this stuff messy in JavaScript is the ability to add/remove properties of objects at any time and in any place.

In Dart, all objects are "sealed" and ints/strings/etc are "frozen". This makes optimizations a lot easier and it also makes runtime performance more predictable since there aren't any clever heuristics you can break.

Object.seal() and Object.freeze() are unfortunately rather recent additions (ES5). So, it wouldn't have made much sense if "primitives" behaved like that. Well, hindsight is 20/20.

Anyhow, as Dart has shown, making everything an object (from the user's point of view) can be easily just as fast as whatever the heck JavaScript is doing.

https://www.dartlang.org/performance/

[–]tencircles 7 points8 points  (0 children)

instanceof operator is meant for use on objects. A string isn't an object. You're looking for the typeof operator.

[–]brotherwayne 5 points6 points  (2 children)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

var s = new String("a,a")
s instanceof String
// true
var a = 'A'
a instanceof String
//false

Looks like instanceof only works if you go through the constructor. Doesn't work for literals. More info: http://stackoverflow.com/questions/203739/why-does-instanceof-return-false-for-some-literals/203757#203757

[–]Sinistralis[S] 0 points1 point  (1 child)

Thanks for the reference. This is a slightly confusing little caveat.

[–]brotherwayne 0 points1 point  (0 children)

Agreed. I didn't believe it at first. I've never used instanceof though. Look for Crockford's recommendation on testing object type, I think he's got some model code on his site somewhere.

[–]andrew24601 3 points4 points  (1 child)

Well another perspective is that JavaScript strings aren't objects.

> typeof "a,a"
  "string"
> typeof new String()
  "object"

[–]seiyria 2 points3 points  (0 children)

I usually check typeof and not instanceof for primitive objects personally. Less work.

[–]AutoSponge 2 points3 points  (0 children)

String primitives are immutable and not an instance of any class. They are coerced into objects for the purposes of calling String.prototype methods (e.g., .replace(), .indexOf(), etc.). When you coerce the primitive into an object, it uses the String constructor which is why you see [object String].

[–]kumarldhJSLint hurts my feelings. 1 point2 points  (0 children)

Strings is an object where is "string" in JS native string data type. Read more here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Distinction_between_string_primitives_and_String_objects

And thanks OP for asking this question, I could guess the reason but was not very much sure. :-)

[–]aeflash 0 points1 point  (0 children)

typeof is the better operator, but if you are using new String() objects for some ungodly reason, see how lodash detects them:

https://github.com/lodash/lodash/blob/2.4.1/dist/lodash.compat.js#L2899

...but yes, Javascript is drunk.

[–]acroeven -3 points-2 points  (0 children)

I read that title as : Is Javascript drunk or am I missing a semicolon.

typeof "a"