I tend to write my Javascript "classes" in c-style.
In C# (for example) we do this
public class Parent {
// stuff
}
public class Child : Parent {
// Protected and public stuff from Parent will be accessible
}
In JS I found the equivalent of this by using proto , in example
var namespace = namespace || {};
namespace.Parent = function() {
// Public variables
self.pubVariable = "I am accessible";
// Private variables
var priVariable = "I'm not accessible outside of self";
// ctor
function self() {}
return self;
}
namespace.Child = (function() {
this.__proto__ = new namespace.Parent();
// ctor
function self() {}
self.init = function() {
// Prints the pubVariable
console.log(pubVariable);
};
return self;
})($);
// Call it (statically)
namespace.Child.init();
While this works it is Webkit and Mozilla only. I've understood that this could somehow be achievable using prototype but can't figure out how. Any advice is appreciated. Thanks!
For parent/child classes, I would do something like this
// your parent class
var Parent = function() {
// parent constructor
console.log("parent constructor!");
// some public properties
this.foo = "foo";
this.bar = "bar";
// a private data member
var secret = "123456";
};
// a parent function
Parent.prototype.something = function() {
console.log("something!");
}
// your child class
var Child = function() {
// call parent constructor
Parent.call(this);
// child constructor
console.log("child constructor!");
// override bar
this.bar = "override!";
};
// the magic!
// child prototype build from parent prototype
Child.prototype = Object.create(Parent.prototype, {constructor: {value: Child}});
Example usage
var c = new Child();
c.something();
// => parent constructor!
// => child constructor!
// => something!
c.foo //=> "foo"
c.bar //=> "override!"
If you're using "namespacing" the concept is identical.
You can see this pattern in a number of libraries
EDIT
Per your comment, here's and added demonstration
var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };
var foo = new Foo();
// call our hello method
// this calls foo.__proto__.hello
foo.hello(); //=> "hello!"
// override `hello` method for this instance
foo.hello = function(){ return "こんにちは"; };
// call our hello method again
// this calls foo.hello because it is defined directly on our instance
// (it has a higher precedence in the lookup chain)
foo.hello(); //=> "こんにちは"
// remove the override
delete foo.hello;
// call our hello method again
// this goes back to calling foo.__proto__.hello
foo.hello(); //=> "hello!"
// remove the method prototype
delete Foo.prototype.hello
// call our hello method one last time
// spoiler: it's gone!
foo.hello(); //=> TypeError: Object [object Object] has no method 'hello'
As you can see, you lose this functionality by directly defining methods on the instance using this.something = function(){};
. I personally prefer defining methods on the prototype because of the added flexibility. This way, the prototype really works like a blueprint. You get all the pre-defined behavior; you can modify if necessary and revert to the original whenever you want, all on a per-instance basis.
ONE MORE THING
In our last example, we had a prototype method and an instance method override. Is there a way to call the original method too? Let's see!
var Foo = function(){};
Foo.prototype.hello = function(){ return "hello!"; };
var foo = new Foo();
foo.hello = function(){ return "こんにちは!"; }
// call override method
foo.hello(); //=> "こんにちは!"
// call original method
Foo.prototype.hello.call(foo); //=> "hello!"
// japanese just one more time...
foo.hello(); //=> "こんにちは!"
This would work too, but I never really have the need. I suppose the benefit is you don't need to know the original class this way :)
// call original method from the instance
foo.__proto__.hello.call(foo); //=> "hello!"
PROTOTYPES!
I think, you want this
// namespace
var namespace = namespace || {};
// Parent Class
namespace.Parent = function() {
this.pubVariable = "I am accessible";
var priVariable = "I'm not accessible outside of this";
}
// Child class
namespace.Child = function() {
// namespace.Parent.call(this);
this.init = function()
{
// returns Parent class' pubVariable
// inherited by namespace.Child.prototype
return this.pubVariable;
}
};
// inherit Parent class
namespace.Child.prototype = new namespace.Parent();
var kid = new namespace.Child();
console.log(kid.init()); // I am accessible
If you use namespace.Parent.call(this)
then Child
class will have it's own copy of pubVariable
but now Child
class is using Parent's pubVariable
.
Also, if you want to share methods
from parent class with sub classes then you should add methods in the parent class' prototype, like this
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
So, when you will inherit it in a subclass like this
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
Another Sub/Child Class
namespace.AnotherChild = function() { // ... };
namespace.AnotherChild.prototype = new namespace.Parent();
In this case both sub/child classes will use the same aMethodInParent()
method from their parent class.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.