我想遵循上面显示的继承结构。我想用这种语法创建一个工程师:
var Mark = new Employee(id).WorkerBee(project).Engineer();
要实现这种语法,我必须按照寄生继承模式创建一个嵌套对象,如下所示:
function Employee(id) {
this.id = id;
this.WorkerBee = function(project) {
this.project = project;
this.Engineer = function() {
...
return this;
};
return this;
};
}
为了避免深层嵌套,我试图用原型重写它。如何重写我的代码以实现与上述相同的目标?
function Employee(id) {
//variables
this.id = id
this.name = "";
this.dept = "general";
//methods
this.getId = function() {
return this.id
}
}
Employee.prototype.WorkerBee = WorkerBee;
function WorkerBee(project) {
//variables
this.projectName = project
this.projects = [];
//methods
this.getProjectName = function() {
return this.projectName
}
return this
}
WorkerBee.prototype.Engineer = Engineer
function Engineer() {
//variables
this.dept = "engineering";
this.machine = "";
//methods
this.getDept = function() {
return this.dept
}
return this
}
var Mark = new Employee("5").WorkerBee("Secret Project").Engineer();
console.log(Mark.getId()) //should print "5"
console.log(Mark.getProjectName()) //should print "Secret Project"
console.log(Mark.getDept()) //should print engineering
答案 0 :(得分:0)
<强>更新强>
好的,我理解了一下。你想要这样做的原因是什么?您是否只想要一个使用多个语句创建多个实例的快捷方式?
C
返回的A().B().C()
实例是否应与使用标准new C()
创建的实例不同?
如果您只想链接构造函数,可以将定义它们的上下文(很可能是全局对象)添加到创建实体的原型链中。你应该能够做到这一点:
var A = function () {};
A.prototype = Object.create(this);
虽然需要new
关键字进行实例化,但这并没有消除。你需要做new (new (new A()).B()).C()
。我不能想到一个不同的方法,而不是使用辅助函数来创建不需要new
关键字的构造函数:
var define = function (init) {
var Constructor = function () {
if (!(this instanceof Constructor)) {
return new Constructor();
}
if (init) {
init.apply(this, Array.prototype.slice.call(arguments));
}
};
Constructor.prototype = Object.create(this);
return Constructor;
};
用法是:
var A = define(function (x, y) {
this.x = x;
this.y = y;
});
var a1 = new A(1, 2);
// a1 instanceof A === true
// a1.x === 1
// a1.y === 2
var a2 = A(1, 2);
// a2 instanceof A === true
// a2.x === 1
// a2.y === 2
如果您有构造函数A
,B
和C
,则可以互换使用以下符号:
var a = new A();
var b = new B();
var c = new C();
var a = A();
var b = B();
var c = C();
var b = A().B();
var c = A().C();
var a = B().C().A();
如果是A().B().C()
,则您无权访问A
和B
的实例。
你能详细说明你的交易是什么吗?
OLD ANSWER:
<德尔> 你有什么是疯狂的,因为你基本上合并了三个构造函数,并使它看起来`WorkerBee`和`Employee`实际上是实例化的,而它们不是。 我不会质疑 new A().B().C()
符号,即使我觉得它很乱。
您可能希望以下列方式使用 instanceof
运算符。
var A = function (x) {
if (!(this instanceof A)) return new A(x);
this.x = x;
};
var B = function (y) {
if (!(this instanceof B)) return new B(y);
this.y = y;
};
var C = function () {
if (!(this instanceof C)) return new C();
};
A.prototype.B = B;
B.prototype.C = C;
您现在可以互换地呼叫 new A()
和A()
,new B()
和B()
以及new C()
和C()
,同时实现相同目标结果,因为两个调用总是返回构造函数的实例。
new A() instanceof A === true
new A().B() instanceof B === true
new A().B().C() instanceof C === true
答案 1 :(得分:0)
基于这些评论,您似乎相信您必须使用这种奇怪的,冗长的机制才能在Employee&lt; - WorkerBee&lt; - Engineer(等等)之间进行继承,但是您不必这样做。吨;正常继承就是你所需要的:
// ==== Employee
function Employee(id) {
this.id = id;
}
// Add Employee methods to Employee.prototype, e.g.:
Employee.prototype.getId = function() {
return this.id;
};
// ==== WorkerBee, derived from Employee
function WorkerBee(id, project) {
// Inheritance, part 1: Chain to the base constructor
Employee.call(this, id);
// WorkerBee stuff
this.project = project;
}
// Inheritance, part 2: Create the object to use for WorkerBee
// instance prototypes, using Employee.prototype as its prototype.
WorkerBee.prototype = Object.create(Employee.prototype);
WorkerBee.prototype.constructor = WorkerBee;
// Add WorkerBee methods to WorkerBee.prototype, e.g.:
WorkerBee.prototype.getProjectName = function() {
return this.project;
};
// ==== Engineer, derived from WorkerBee
function Engineer(id, project) {
// Inheritance, part 1: Chain to the base constructor
WorkerBee.call(this, id, project);
}
// Inheritance, part 2: Create the object to use for Engineer
// instance prototypes, using WorkerBee.prototype as its prototype.
Engineer.prototype = Object.create(WorkerBee.prototype);
Engineer.prototype.constructor = Engineer;
// Add Engineer methods to Engineer.prototype, e.g.:
Engineer.prototype.getDept = function() {
return "Engineering";
};
// ==== Usage
var mark = new Engineer("5", "Secret Project");
snippet.log(mark.getId()); // "5"
snippet.log(mark.getProjectName()); // "Secret Project"
snippet.log(mark.getDept()); // "Engineering"
&#13;
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
这是使用JavaScript中的构造函数进行原型继承的标准方法(目前为止;在ES6中,您使用新的class
功能,这基本上做同样的事情,一些语法糖)。只需添加Manager
(源自Employee
)和SalesPerson
(源自WorkerBee
)。
在旧浏览器上,您可能需要Object.create
的部分填充,如下所示:
if (!Object.create) {
Object.create = function(proto, props) {
if (typeof props !== "undefined") {
throw "The two-argument version of Object.create cannot be polyfilled.";
}
function ctor() { }
ctor.prototype = proto;
return new ctor();
};
}
有些转发器用于将ES6源与class
一起使用并将其转换为ES5代码。还有我的Lineage
脚本,这使得继承更加简洁。