1

I have some code cannot understand.
Checked code below on smjs. I could not understand why false returned.
Isn't a prototype object an instance?

js> "".__proto__
(new String(""))
js> (new String("")) instanceof String
true
js> "".__proto__ instanceof String
false
takanopontaro
  • 217
  • 1
  • 2
  • 12
  • `__proto__` isn't a String, its an Object – yoavmatchulsky Jun 22 '13 at 14:17
  • @yoavmatchulsky `String` is a type of object. He's talking about boxed string, not the value type. – Benjamin Gruenbaum Jun 22 '13 at 14:18
  • The confusion might come from misinterpreting the first output. In your chosen JS engine the *string representation* of the prototype object is `'(new String(""))'`. That doesn't mean that `"".__proto__ === (new String(""))`. – JJJ Jun 22 '13 at 14:22
  • @Juhana If you see my answer it links to the language specification. The language specification states that the string prototype is itself a string object. (=== wouldn't hold anyway since `String` objects (well, strings boxed) are not a value type. – Benjamin Gruenbaum Jun 22 '13 at 14:26
  • @BenjaminGruenbaum Yes, well, I didn't mean *literally* `===` (bad choice of symbol). Is it not possible that the JavaScript shell uses `(new String(""))` as a representation of the prototype object? – JJJ Jun 22 '13 at 14:33
  • Ah, that sure is possible. – Benjamin Gruenbaum Jun 22 '13 at 14:34
  • @BenjaminGruenbaum I've got lost in the `"".__proto__.__proto__` part, seeing as `"".__proto__ === String.prototype`, how come `"".__proto__.__proto__` is an Object when `String.prototype.prototype` doesn't exist erm enough ecmas for a day. – Fabrício Matté Jun 22 '13 at 14:46
  • 2
    This question is basically the same as http://stackoverflow.com/questions/17248437/learning-array-prototype-and-calculating-its-length – user123444555621 Jun 22 '13 at 14:48
  • Thanks for your reply. I used console of SpiderMonkey and when used console of Google Chrome, got same result. And this code below too. `js> "".__proto__.constructor -> function String() { [native code] }` So I have expected a prototype object of a String object is an instance of String. But not :( – takanopontaro Jun 22 '13 at 14:51
  • Look at the question Pumbaa80 linked to. It really is the same. `String.prototype` **is** a string (according to the specification), but it is not an instance of the constructor function `String`. And because of the way `instanceof` works, it will return `false`. To quote the [spec](http://es5.github.io/#x15.5.4): *"The String prototype object is itself a String object (its [[Class]] is "String") whose value is an empty String. The value of the [[Prototype]] internal property of the String prototype object is the standard built-in Object prototype object (15.2.4)."* – Felix Kling Jun 22 '13 at 14:53
  • Now it makes some sense, `String.prototype` and `"".__proto__` return a String object in my SpiderMonkey shell. – Fabrício Matté Jun 22 '13 at 14:55

1 Answers1

4

This is basically the same as Learning Array.prototype and calculating its length.

String.prototype is a string, according to the specification, §15.5.4, Properties of the String Prototype Object:

The String prototype object is itself a String object (its [[Class]] is "String") whose value is an empty String.

The value of the [[Prototype]] internal property of the String prototype object is the standard built-in Object prototype object (15.2.4).

But it is not an instance of the constructor function String.

instanceof works by comparing the prototype of the instance with the prototype property of the constructor function (§15.3.5.3), i.e.

Object.getPrototypeOf(String.prototype) === String.prototype

So, you are testing whether String.prototype is it's own prototype, which is of course false. The prototype of String.prototype is, as mentioned in the specification, Object.prototype.


A word regarding the first example:

> js> "".__proto__
 (new String(""))

You have to keep in mind that the console (or RELP) uses some heuristic to format and present values. For example it might read the constructor property of the object to determine what "kind" of value it is and format the output accordingly. That's what the Chrome console is doing:

var str = new String('foo');
str instanceof String
=> true
console.dir(str);
=> String

var obj = {};
console.dir(obj);
=> Object                   // looks good

obj.constructor = String;
=> console.dir(obj); 
String                      // uhm what?
obj instanceof String
=> false

It happens that every prototype object has a constructor property, which points back to the function it is the prototype object of, i.e.

function Foo() {}
Foo.prototype.constructor === Foo;
=> true
console.dir(Foo.prototype)
=> Foo

So if you log a prototype object, the output might suggest that the object is an instance of the function itself although it isn't, just because of the constructor property.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Hi, Felix. Thanks for your answer. I didn't know about implementation of instanceof operator for details. I understood clearly about result of my code :) But one more question. `But it is not an instance of the constructor function String.` If so, what kind of object String.prototype refers? – takanopontaro Jun 22 '13 at 15:39
  • I'm glad I could help! `String.prototype` is still a string object but it was not constructed by calling `String`. See it as a string that was constructed *internally* in a different way. – Felix Kling Jun 22 '13 at 15:43
  • I see. String.prototype is a string object but not an object created by using "new". It's created by using internal way. Thx! – takanopontaro Jun 22 '13 at 15:57
  • You're welcome! If you find that an answer provided a solution to your question, please click on the checkmark next to it to "accept" it. This shows other users that that answer solved your problem. – Felix Kling Jun 22 '13 at 16:00