Reputation: 10645
I couldn't find anything matching my exact question so sorry if this is a duplicate.
Given the code:
var Foo = function () {
};
Foo.prototype.log = function (message) {
console.log(message);
};
var Bar = function () {
};
Bar.prototype = Object.create(Foo.prototype);
I can inherit the log(message)
function of Foo
within Bar
and call the following code without issue.
var bar = new Bar();
bar.log("this works");
If I then move the assignment of the prototype to the constructor like follows:
var Foo = function () {
};
Foo.prototype.log = function (message) {
console.log(message);
};
var Bar = function () {
Bar.prototype = Object.create(Foo.prototype);
};
The call to log(message)
will fail
TypeError: bar.log is not a function
Now I'm probably missing something obvious but why is this the case? How would I lazily inherit properties?
The use case I am imagining is inheriting objects from an asynchronously loaded JavaScript file, something like a google.maps.OverlayView
whilst being able to already have the inherited object present in the page.
Upvotes: 0
Views: 176
Reputation: 122986
When you assign the prototype within the constructor, it will be assigned after first instantiation. In the code snippet (or this jsfiddle with a few more examples and inheritance check) that situation is demonstrated in barfoo1
and barfoo2
. A solution would be to copy Foo.prototype
within the Bar
constructor. Another solution is to return an instance on assigning the prototype within the constructor. Both are demonstrated in the FooBar
and FooFoo
constructor in the snippet respectively.
Furthermore you can assign the prototype just using Xyz.prototype = Abc.prototype
(no need for Object.create
here), or use Xyz.prototype = new Abc
.
var Foo = function () {};
Foo.prototype.log = function (msg) {
log(msg);
}
var Bar = function () {
Bar.prototype = Object.create(Foo.prototype);
};
var FooBar = function () {
if (!FooBar.prototype.log) {
for (var l in Foo.prototype) {
FooBar.prototype[l] = Foo.prototype[l];
}
}
}
var FooFoo = function () {
if (!FooFoo.prototype.log) {
FooFoo.prototype = new Foo;
return new FooFoo;
}
}
var BarFoo = function () {
if (!BarFoo.prototype.log) {
BarFoo.prototype = Object.create(Foo.prototype);
}
}
var bar = new Bar;
var foobar = new FooBar;
var barfoo1 = new BarFoo;
var barfoo2 = new BarFoo;
var doublefoo = new FooFoo;
try { bar.log('hello!'); }
catch(e) {log('bar.log failed => ', e.message);}
try { barfoo1.log('barfoo1 hello!'); }
catch(e) {log('barfoo1.log failed => ', e.message);}
try { barfoo2.log('barfoo2 hello!'); }
catch(e) {log('barfoo2.log failed => ', e.message);}
foobar.log('foobar just works (Foo.prototype copied)');
doublefoo.log('doublefoo just works too (instantiation on assigning Foo.prototype)');
function log() {
document.querySelector('#result')
.innerHTML += '<p>'+ [].slice.call(arguments).join('') +'</p>';
}
<div id="result"></div>
Upvotes: 1
Reputation: 610
James if jQuery is possible in your code you could attempt something like this -
var Bar = function() {};
$.ajax({
url: "http://maps.google.com/api/scriptfile.js",
dataType: "script",
success: function(script, status) {
Bar.prototype = Object.create(Foo.prototype);
}
});
Hope this helps!
Upvotes: 0