Object and String prototypes are not prototypes of defined strings?

微笑、不失礼 提交于 2019-12-30 22:59:16

问题


I'm trying to understand how JavaScript's prototype-based inheritance works. I was expecting the below outputs would evaluate as true. Why is this?

var myStr = "Sample";
String.prototype.isPrototypeOf(myStr); // false
Object.prototype.isPrototypeOf(myStr); // false

回答1:


JavaScript has both primitive strings and string objects. What you've written there is a primitive string. The Object.prototype.isPrototypeOf method always returns false for any primitive, so your results make sense.

If you used a string object, you'd get true:

var myStr = new String("Sample");
console.log(String.prototype.isPrototypeOf(myStr)); // true
console.log(Object.prototype.isPrototypeOf(myStr)); // true

You're probably wondering: If it's a primitive, then why can I call methods on it that are defined on String.prototype?

The answer is that the specification defines that if you use a property accessor on a primitive string, a temporary string object with an equivalent character sequence is created (with String.prototype as its prototype), and the property is then read from that temporary object. (The same is done with numbers.)

We can prove that the temporary object is created by adding a method to String.prototype that returns that object (just for the purposes of illustration):

Object.defineProperty(String.prototype, "foo", {
  value: function() {
    return this;
  }
});
var primitive = "string";
var object = primitive.foo();
console.log(primitive === object);                      // false
console.log(primitive == object);                       // true
console.log(String.prototype.isPrototypeOf(primitive)); // false
console.log(String.prototype.isPrototypeOf(object));    // true



回答2:


This is because the string primitives are not string objects. If you want the above code to work, the string should be constructed via the String class, as in:

var myStr = new String("Sample");
String.prototype.isPrototypeOf(myStr); // true



回答3:


Basically, isPrototypeOf only works on objects, and string primitives are not objects, they are primitives.

If you were using the String wrapper object, it would work (but don't do that!):

var myStr = new String("Sample");
console.log(String.prototype.isPrototypeOf(myStr)); // true
console.log(Object.prototype.isPrototypeOf(myStr)); // true

But the wrapper objects are generally bad practice, so don't use them.

Alternately, you could cast them to their object form when testing.

var myStr = "Sample";
console.log(String.prototype.isPrototypeOf(Object(myStr))); // true
console.log(Object.prototype.isPrototypeOf(Object(myStr))); // true


来源:https://stackoverflow.com/questions/41127095/object-and-string-prototypes-are-not-prototypes-of-defined-strings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!