4

Say I have one object with prototypal properties that I have manually set.

An example would be

function A() {

};

A.prototype.B = function() {

};

A.prototype.C = function() {

};

A.prototype.D = function() {

};

How can I extend another object with A's prototype?

What I have tried is this;

// obj = extend to object
// obj2 inherit from object

for (var prop in obj2.prototype) {
            if (obj2.prototype.hasOwnProperty(prop)) {
                obj.prototype[prop] = obj2.prototype[prop];
            }
        }

Does using obj2.hasOwnProperty(prop) ensure that only the properties that are on A's prototype that I have will get copied?

Is there a better way of doing this?

user2251919
  • 665
  • 2
  • 11
  • 23
  • what is obj2? is it the same as A? – Dan May 15 '13 at 00:55
  • Yes, obj2 would be a in the example – user2251919 May 15 '13 at 00:57
  • This should work as expected, you are using hasOwnProperty correctly. If your goal was just to make a shallow copy from one object's prototype to another, then there is no better way. – Dan May 15 '13 at 01:04
  • Are you familiar with [`Object.create`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create)? That MDN link might clear things up a bit for you. – apsillers May 15 '13 at 02:10

1 Answers1

1

Generally, it's not always advisable to try and emulate patterns from other languages into Javascript. Javascript uses prototypal inheritance, and not standard OO inheritance (such as what you do in Java). Yes, you can copy methods from one prototype to another, but it is not always advisable, because you're really blowing the encapsulation of the inner object out of the water. If you do want to copy methods, you can do so simply by setting one objects prototype equal to the other.

Here is one pattern for doing inheritance

// object we want to inherit from
function bar() {}
bar.prototype.original = function() {}

// object which will inherit bar
function foo() {}
// first map prototypes
foo.prototype = new bar();

// add additional methods to foo
foo.prototype.somethingElse = function() {}

Instead of doing new bar() you could do Object.create(bar), as some of the commenters have pointed out, but that is not supported in IE8 and below. The only functional difference between the two is that new bar() will execute the constructor of bar, while the latter will not, which may or may not matter to you. Object.create() is technically the more correct way to go, but can be a deal breaker unless you are willing to lose IE8 or use a shim.

Here is another pattern, my preferred, using composition instead

// object we want to inherit from
function bar() {}
bar.prototype.original = function() {}

function foo() {
    this.bar = new bar();
}
foo.prototype.somethingElse = function() {
    // foo has a bar, but isn't a bar
    this.bar.original();
}
Owen Allen
  • 11,348
  • 9
  • 51
  • 63
  • @apsillers Whoops, you are correct, I updated it to be new bar() and then made sure that a new foo() and new bar() resulted in different signatures. – Owen Allen May 15 '13 at 02:14
  • @Nucleon: No, do not use `new bar()` for the prototype object! – Bergi May 15 '13 at 02:34
  • Why? Here's an example from Google with their map API using this exact pattern: https://developers.google.com/maps/documentation/javascript/examples/overlay-simple. `USGSOverlay.prototype = new google.maps.OverlayView();`. If there is something wrong with this approach I would love to know. – Owen Allen May 15 '13 at 16:42
  • Check out http://stackoverflow.com/questions/12592913/what-is-the-reason-to-use-the-new-keyword-here - while it may work for some (or even, most) cases it's a bad practise – Bergi May 15 '13 at 17:08
  • @Bergi I've created a question at P.SE ([Why is the use of constructors discouraged when creating prototypes?](http://programmers.stackexchange.com/questions/198267/why-is-the-use-of-constructors-discouraged-when-creating-prototypes)) if you're interested in addressing the question from a purely theoretical standpoint (i.e., without needing to explain yet again the particular mechanics of JS prototyping). I made that question before you posted the above link, which I'm digesting now. – apsillers May 15 '13 at 17:22