0

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?

user1142130
  • 1,617
  • 3
  • 20
  • 34
  • Only constructor functions do have a `.prototype` property. What are you actually trying to do? – Bergi Apr 30 '15 at 21:18
  • I answered a similar question earlier today, hope this is helpful: http://stackoverflow.com/a/29977006/4556448 – radiaph Apr 30 '15 at 21:33
  • Does this answer your question? [Extending object literal](https://stackoverflow.com/questions/26015216/extending-object-literal) – Suma Jan 08 '20 at 10:04

3 Answers3

2

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.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Let's say "normal" browsers these days :-) "Newer" browsers would implement `Reflect.setPrototypeOf` (ES6), only old browsers do not support ES5. – Bergi Apr 30 '15 at 21:21
  • @Bergi - I made the reference more specific (IE9+). Even ES6 browsers will support `Object.getPrototypeOf()`, right? – jfriend00 Apr 30 '15 at 21:24
  • Yes, ES6 is backwards-compatible so they will implement ES5 `Object.getPrototypeOf` for sure. – Bergi Apr 30 '15 at 21:27
  • 1
    @user1142130 - I've added lots more detail to my answer to address the various pieces of your question. Let me know if you still need any more explanation. – jfriend00 Apr 30 '15 at 21:35
0

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.

Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128
  • 1
    It does have a prototype (`obj`), but not a `.prototype` property. – Bergi Apr 30 '15 at 21:19
  • 1
    `temp` does inherit from `obj` which does inherit from `Object.prototype` which does inherit from `null` – Bergi Apr 30 '15 at 21:20
  • @Bergi in your console, do `var temp = Object.create({})` Then try and call `temp.prototype`. You will see it does not exist. Now, you could create it if you wanted to... you could do `temp.prototype = {}; temp.prototype.second_prop = 'second_property';` but it will behave like a normal object key, not like the actual Object prototype – Matthew Herbst Apr 30 '15 at 21:21
  • @Bergi temp inherits nothing. It is a reference, not an extension of Object itself. – Matthew Herbst Apr 30 '15 at 21:22
  • 1
    @MatthewHerbst: I didn't say there was a `temp.prototype`, I did say that the `temp` object does have a prototype - which is `obj`. Because that's how `Object.create` works… – Bergi Apr 30 '15 at 21:23
  • @Bergi test it out in your javascript console in your web browser. That's not what's happening. – Matthew Herbst Apr 30 '15 at 21:24
  • @MatthewHerbst: For sure it is (I don't need to test this). Try `obj = {}; temp = Object.create(obj)` yourself and closely inspect the result. – Bergi Apr 30 '15 at 21:25
  • @Bergi I'm not going to keep repeating myself. Based on your last comment, try doing `temp.prototype`. You will see it doesn't exist. The prototype is part of the Object construction. So again, you can create the prototype if you want by doing `temp.prototype = {}` and then doing `temp.prototype.second_prop = "second_property";` – Matthew Herbst Apr 30 '15 at 21:31
  • Of course it doesn't exist! I never said otherwise, and I'm not going to repeat that. Please re-read my comments. – Bergi Apr 30 '15 at 21:32
  • Then what exactly is your question? Do you want to know why your code fails or why temp does inherit from Object? The two are very different questions. – Matthew Herbst Apr 30 '15 at 21:34
  • @MatthewHerbst: I didn't ask a question, I tried to help clarifying. – Bergi Apr 30 '15 at 21:40
0

.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' }
jtrezza
  • 354
  • 4
  • 13