Extending prototype on object literal

2019-08-29 19:17发布

问题:

If I have the following code, why does it return an error saying Cannot set property 'second_prop' of undefined . I thought that you can extend the prototype property and add more variables and methods to the object prototype. Since the two console statements return 'Object' and true, then why does it return an error of undefined. My thinking is, if the 'obj' is an object of type Object, then I should be able to do temp.prototype.newproperty? So then the Object will have a 'newproperty'. But I'm obviously wrong, so there's something I am missing here. Even more, why do I need to do Object.create() when the obj is already an object literal? Isn't it already an object? I'm just looking at some examples and trying to understand this

    var obj = {
        first_property: 'first property'
    }
    console.log(typeof obj);
    console.log(obj instanceof Object);

    var temp = Object.create(obj);
    temp.prototype.second_prop = 'second property'

Output

//object
//true
//Uncaught TypeError: Cannot set property 'second_prop' of undefined

So, why can't i do temp.prototype or obj.prototype?

回答1:

If I have the following code, why does it return an error saying Cannot set property 'second_prop' of undefined

A Javascript literal object is already an instantiated Object and does not have the .prototype property. That property is on a constructor function, not an already instantiated object. In any current browser (IE9+), you can use Object.getPrototypeOf() to obtain the prototype for an already built object.

But, it sounds more like you'd rather just clone an object and then add properties to the clone. Or if you want both objects to have the same additional property, then add the property, then clone it. Or, if you just want to use your literal object, then just use it as it is.

Once an object has already been constructed, the prototype is an internal property and it is generally not meant for you to be messing with it. If you intend to change the prototype for all objects, you should be changing the prototype on the constructor. If you meant to be changing properties for just this instance of the object, then just change properties on the object itself, not the prototype.

As always, if you describe what you're actually trying to accomplish (rather than why your own solution does not do what you expected), we can help you much better.

I thought that you can extend the prototype property and add more variables and methods to the object prototype.

You can, but the .prototype property is on a constructor, not on an already built object.

Since the two console statements return 'Object' and true, then why does it return an error of undefined. My thinking is, if the 'obj' is an object of type Object, then I should be able to do temp.prototype.newproperty?

You are confusing being an instantiated object with being a constructor with a prototype. An instantiated object has a prototype as an internal property, not as a public .prototype property. So, when something reports instanceof, that means it is literally an instance of that type of object (and thus has that type of objects prototype in its internal prototype chain), not that it's a constructor with the public .prototype property.

Even more, why do I need to do Object.create() when the obj is already an object literal? Isn't it already an object?

The purpose of Object.create() is to create a new object, using an existing object as the prototype. If you're declared a Javascript literal and you just want to use the literal as an object by itself, then there is NO reason to use Object.create() on it. Just use the literal as the already built object that it is.



回答2:

temp doesn't have a prototype. Object has a prototype. You can change the prototype for all Objects by calling Object.prototype but you can't change it for just once object.



回答3:

.prototype is a property that is not allways linked to the actual prototype of the object. The real prototype can be accesed via .__proto__

var obj = {
    first_property: 'first property'
}
console.log(typeof obj);
console.log(obj instanceof Object);

var temp = Object.create(obj);

temp.__proto__.second_prop = 'second property';

console.log(Object.getPrototypeOf(temp));

//{ first_property: 'first property',
//second_prop: 'second property' }