这个问题是关于Javascript的,但我学到的第一种编程语言是Java,所以我最容易与之相关。
在Java中,对象可以访问静态成员,如Oracle的文章Understanding Class Members所示:
public class Bicycle {
// INSTANCE fields
private int cadence;
private int gear;
private int speed;
// CONSTRUCTOR
constructor Bicycle(c,g,s) { /*...*/ }
//...
// STATIC fields
private static int numberOfBicycles = 0;
}
您也可以使用对象引用来引用静态字段
myBike.numberOfBicycles
除了可以访问静态字段的对象之外,子类也可以,如Inheritance中所述。
public class MountainBike extends Bicycle {
public int seatHeight;
constructor MountainBike(c,g,s,h) { /*...*/ }
private static int mountainBikePrice = 324;
}
MountainBike
现在有4个实例字段:cadence
,gear
,speed
和seatHeight
;和2个静态字段:numberOfBicycles
和mountainBikePrice
。
我想在我的Javascript程序中模拟这种行为,但是,由于JS是面向原型而不是面向对象的,因此对象和子类无法访问他们的"类"成员。
// constructor
function Bicycle(c,g,s) {
this.cadence = c
this.gear = g
this.speed = s
}
// instance methods
Bicycle.prototype.go = function () { /*...*/ }
Bicycle.prototype.stop = function () { /*...*/ }
// STATIC field
Bicycle.numberOfBicycles = 0 // <-- I want THIS field inherited
当我通过var myBike = new Bicycle()
创建一个新的Bicycle对象时,我可以访问实例方法myBike.go()
等,但我无法通过myBike.numberOfBicycles
获取静态字段。 Java的。获得此功能的唯一方法是致电Bicycle.numberOfBicycles
。
此外,当我创建一个新的子类时,它无法访问其父类的字段。
// subclass constructor
function MountainBike(c,g,s,h) {
Bicycle.call(this,c,g,s)
this.seatHeight = h
}
// vvvvvvvv extension mechanism... ignore this vvvvvvvvvv
MountainBike.prototype = Object.create(Bicycle.prototype)
MountainBike.prototype.constructor = MountainBike
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// STATIC field
MountainBike.mountainBikePrice = 324
如果我调用MountainBike.numberOfBicycles
我得到undefined
(这在Java中不会发生 - 它将返回父项的值。)
除了分配Bicycle.prototype.numberOfBicycles = 0
之外,对象必须有一种更简单的方法来继承其类的属性,并且子类可以继承其父级的属性。
myBike.class
?如果是,那么我可以致电myBike.class.numberOfBicycles
。MountainBike.super
?答案 0 :(得分:1)
实际上,您要查找的属性为constructor
(与myBike.constructor.numberOfBicycles
中的属性一样)。
对象的构造函数(类似于)Java中的实例类。可能最好采取一些盐,因为这些概念不完全可以互换。
修改强>
所以我看到你基本上是在尝试使用原型和构造函数hacks在JavaScript中创建一些完整的“类”实现(这很好)。 Backbone在extend函数中有一个有趣的方法。相关来源如下(请参阅此代码许可的问题底部):
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
// Inherits constructor if not specified in child props.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
// copy all properties from parent and from static properties
// into child
_.extend(child, parent, staticProps);
// figure out child prototype (kind of like you had)
child.prototype = Object.create(parent.prototype);
_.extendOwn(child, protoProps);
child.prototype.constructor = child;
// Save super for later access (answers question 2)
child.__super__ = parent.prototype;
return child;
};
注释是我的。我编辑了代码,以揭示OP发布的一些相似之处(即使用Object.create
代替_.create
)。使用它的方法是在父Parent.extend = extend;
中设置,然后使用Child = Parent.extend({...new properties and methods...},...)
创建子类。
我决定继续发布整个函数,因为它可能包含您尚未询问的问题的解决方案(例如构造函数的继承)。 特别针对问题2 ,Backbone开发人员决定使用__super__
在子级中显式保存父类,因此您也可以在继承代码中执行此操作(在调用之后) Object.create
)。
使用ES2015类和继承extends
(这里是some good docs on it)可能更有意义。对它的支持不是很好,所以你需要使用预处理器,如Babel。以下是这些类的示例:
class Parent {...}
class Child extends Parent {...}
发布了Backbone代码片段的许可证:
(c)2010-2016 Jeremy Ashkenas,DocumentCloud和Investigative Reporters&amp;编辑。 Backbone可以在MIT许可下自由分发 所有细节和文件:
http://backbonejs.org