问题
I'm trying to understand prototypal inheritance in Javascript, but failing to apply to the following case. Any help would be appreciated.
I'm defining a constructor as follows:
var base = function() {
var priv = "private"; // Private
var publ = "public"; // Public through a getter/setter (below)
// The object to return
var f = {};
f.publ = function (new_val) {
if (!arguments.length) {
return publ;
}
publ = new_val;
return f;
};
return f;
};
With this constructor, I can create objects by calling base();
. These objects have a public method (publ).
Now, following the same structure, I would like to have a new constructor that creates objects that inherits from objects created by the "base constructor" defined above:
var myclass = function () {
// Other parameters defined here
var f = function () {
// publ is inherited
console.log(f.publ());
};
// Trying to set the prototype of f to the object created by "base()"
f.prototype = base();
// Other methods defined here
return f;
};
With f.prototype = base();
I want to make f inherit all the methods that are defined in the object returned by base()
, but trying to call f.publ complains because f doesn't have method publ
Any help in understanding what is going on would be welcome
M;
回答1:
The most common way to do prototypal inheritance is as follows:
function Base() {
var priv = "private";
this.publ = "public";
}
You can now create instances of Base
using new Base
. Next we create MyClass
:
MyClass.prototype = new Base;
function MyClass() {
alert(this.publ);
}
Finally you can create instance of MyClass
using new MyClass
as follows:
var a = new MyClass; // alerts "public"
See the demo for yourself: http://jsfiddle.net/b3QyE/
Prototypal inheritance in JavaScript can get a little confusing because it's constructor-centric instead of prototype-centric which is why I prefer using the following utility function to create "classes":
function defclass(base, body) {
var uber = base.prototype;
var prototype = Object.create(uber);
var constructor = (body.call(prototype, uber), prototype.constructor);
constructor.prototype = prototype;
return constructor;
}
Using defclass
you can now restructure your code as follows:
var Base = defclass(Object, function () {
this.constructor = function () {
var priv = "private";
this.publ = "public";
};
});
var MyClass = defclass(Base, function (uber) {
this.constructor = function () {
uber.constructor.call(this);
alert(this.publ);
};
});
It's much more readable and understandable. Everything is encapsulated within a single function scope and nothing is dangling out of place. In addition you don't need to understand prototypal inheritance to use it. See the updated demo: http://jsfiddle.net/b3QyE/2/
If you notice we're calling the Base
class constructor function from the MyClass
constructor. This allows you to initialize the instance using the Base
class constructor. You can call any method of the Base
class via uber
.
To learn more about prototypal inheritance take a look at the following answers:
- JavaScript inheritance and the constructor property
- How to achieve pseudo-classical inheritance right on the class declaration?
- Benefits of prototypal inheritance over classical?
来源:https://stackoverflow.com/questions/21653887/prototype-chain-in-javascript-not-updated