我倾向于以c风格编写我的Javascript“类”。
在C#中(例如)我们这样做
public class Parent {
// stuff
}
public class Child : Parent {
// Protected and public stuff from Parent will be accessible
}
在JS中,我在示例
中使用 proto 找到了相同的内容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();
虽然这有效但它只是Webkit和Mozilla。我已经明白,这可以通过原型以某种方式实现,但无法弄清楚如何。任何建议表示赞赏。谢谢!
答案 0 :(得分:6)
对于父/子课程,我会做这样的事情
// 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}});
使用示例
var c = new Child();
c.something();
// => parent constructor!
// => child constructor!
// => something!
c.foo //=> "foo"
c.bar //=> "override!"
如果您使用“命名空间”,则概念是相同的。
您可以在许多库中看到此模式
修改
根据你的评论,这里是并添加了演示
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'
如您所见,通过使用this.something = function(){};
直接在实例上定义方法,您将失去此功能。我个人更喜欢在原型上定义方法,因为它增加了灵活性。这样,原型就像蓝图一样。你得到了所有预先定义的行为;您可以根据需要进行修改,并在每个实例的基础上恢复原始版本。
还有一件事
在我们的上一个例子中,我们有一个原型方法和一个实例方法覆盖。有没有办法调用原始方法?我们来看看吧!
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(); //=> "こんにちは!"
这也可以,但我从来没有真正的需要。我认为好处是你不需要以这种方式知道原始类:)
// call original method from the instance
foo.__proto__.hello.call(foo); //=> "hello!"
PROTOTYPES!
答案 1 :(得分:1)
我想,你想要这个
// 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
如果您使用namespace.Parent.call(this)
,那么Child
类将拥有自己的pubVariable
副本,但现在Child
类正在使用Parent pubVariable
。
另外,如果你想从父类与子类共享methods
,那么你应该在父类的原型中添加方法,就像这样
namespace.Parent = function() { //... }
namespace.Parent.prototype.aMethodInParent = function(){ //... };
所以,当你将在像这样的子类中继承它时
namespace.Child = function() { // ... };
namespace.Child.prototype = new namespace.Parent();
另一个子/子课程
namespace.AnotherChild = function() { // ... };
namespace.AnotherChild.prototype = new namespace.Parent();
在这种情况下,两个子/子类都将使用父类中的相同aMethodInParent()
方法。