从另一个实例初始化 JS 对象(运行时继承)
Initializing JS object from another instance (runtime inheritance)
我想实现这个:
var player = new Player (socket, x, y)
player.on ('event1', function () {});
player.emit ('event2', data);
其中 socket 是外部提供的 Socket 实例。
所以基本上我需要从 Socket 继承 Player,但是从 Socket 的实例初始化它:
var Player = function (socket, x, y)
{
.....?
this.x = x;
this.y = y;
}
知道如何以最简单、最优雅的方式做到这一点吗?
根据你的问题,我假设你已经考虑过但拒绝使用组合:
var Player = function (socket, x, y)
{
this.socket = socket;
this.x = x;
this.y = y;
};
用法:
var player = new Player(socket, x, y);
player.socket.on(/*...*/);
player.socket.emit(/*...*/);
FWIW,我可能会使用组合。
但如果你不想,你至少有两个选择:
真正继承,使用socket
作为新对象的原型:
在这种情况下,您可能不会使用 new
:
var Player = function (socket, x, y)
{
var obj = Object.create(socket);
obj.x = x;
obj.y = y;
return obj;
};
用法:
var player = Player (socket, x, y); // No `new` here, although it's harmless
player.on ('event1', function () {});
player.emit ('event2', function () {});
(尽管如果您确实使用了 new
,那将是无害的——由 new
创建的对象将被丢弃,因为 Player
returns 是非-null
对象引用,因此会覆盖 new
的默认结果。)
但是,如果您依赖继承 Player.prototype
的对象,这将不起作用。您可以 复制 从 Player.prototype
到实例的所有内容,方法是将以下代码添加到上面:
var key;
for (key in Player.prototype) {
if (Player.prototype[key] !== Object.prototype[key]) {
this[key] = Player.prototype[key];
}
}
将 Player.prototype
(及其原型,除了 Object.prototype
之外的任何属性复制到玩家对象上。不太理想,但功能齐全,这只是意味着您需要确保 Player.prototype
在创建第一个播放器之前包含所有内容。此外,instanceof
对玩家无效。
只需连接您想要的位,而无需实际使用 socket
作为原型,方法是将绑定函数添加到实际路由到 [=17= 的 Player
实例]:
var Player = function (socket, x, y)
{
this.on = socket.on.bind(socket);
this.emit = socket.emit.bind(socket);
this.x = x;
this.y = y;
};
然后使用 new
.
或者更冗长一点,但如果您需要,可以让您有机会进入中间:
var Player = function (socket, x, y)
{
this.socket = socket;
this.x = x;
this.y = y;
};
Player.prototype.on = function() {
return this.socket.on.apply(this.socket, arguments);
};
Player.prototype.emit = function() {
return this.socket.emit.apply(this.socket, arguments);
};
以上两个都使用了 ES5 中可以填充的特性。从 Socket
、on
和 emit
,我猜你正在使用 NodeJS,所以你正在使用 V8 并且你拥有这些功能。但是,如果不是,以及其他有类似问题的人:第一个解决方案使用 Object.create
的单参数版本,第二个使用 Function#bind
。如果您需要支持较旧的 JavaScript 引擎,只需查找它们的 polyfill,它们都非常小。
术语 inheritance
在 JS 中与其他语言不同。具体来说,很多人一想到inheritance
,就会想到JS中不存在的classical inheritance
。相反,JS 使用 delegation 的概念来对对象进行原型设计,以模拟类似继承的行为。根据您的描述,您似乎希望 Player
的实例具有属于 Socket
的功能。在那种情况下,您所描述的更像是 Player
委托给 Socket
.
的实例
下面是一些示例代码:
// assuming you have code that defines what a socket is
var Player = function (x, y) {
var socket = new Socket();
var p = Object.create( socket );
p.x = x;
p.y = y;
return p;
};
Player
的实例现在可以将 属性 查找委托给 socket
实例。
So basically I need to inherit Player from Socket
不,你不知道。继承是一种 是一种 关系,而 Player
可能不是 Socket
。另一方面,它可能会 使用 一个 Socket
实例 - 这种类型的关系可以通过 复合 关系建模。
因此您需要将 Socket
实例注入到您的 Player
构造函数中,以便在生成的 Player
实例中使用 player
.
你在这里试图做的是使用继承来重用代码,多年来这已被证明是一种有缺陷的方法,因为它在父对象和子对象之间引入了紧密的隐式(通常是不需要的)耦合.根据您问题中的信息,组合是可行的方法。
我想实现这个:
var player = new Player (socket, x, y)
player.on ('event1', function () {});
player.emit ('event2', data);
其中 socket 是外部提供的 Socket 实例。
所以基本上我需要从 Socket 继承 Player,但是从 Socket 的实例初始化它:
var Player = function (socket, x, y)
{
.....?
this.x = x;
this.y = y;
}
知道如何以最简单、最优雅的方式做到这一点吗?
根据你的问题,我假设你已经考虑过但拒绝使用组合:
var Player = function (socket, x, y)
{
this.socket = socket;
this.x = x;
this.y = y;
};
用法:
var player = new Player(socket, x, y);
player.socket.on(/*...*/);
player.socket.emit(/*...*/);
FWIW,我可能会使用组合。
但如果你不想,你至少有两个选择:
真正继承,使用
socket
作为新对象的原型:在这种情况下,您可能不会使用
new
:var Player = function (socket, x, y) { var obj = Object.create(socket); obj.x = x; obj.y = y; return obj; };
用法:
var player = Player (socket, x, y); // No `new` here, although it's harmless player.on ('event1', function () {}); player.emit ('event2', function () {});
(尽管如果您确实使用了
new
,那将是无害的——由new
创建的对象将被丢弃,因为Player
returns 是非-null
对象引用,因此会覆盖new
的默认结果。)但是,如果您依赖继承
Player.prototype
的对象,这将不起作用。您可以 复制 从Player.prototype
到实例的所有内容,方法是将以下代码添加到上面:var key; for (key in Player.prototype) { if (Player.prototype[key] !== Object.prototype[key]) { this[key] = Player.prototype[key]; } }
将
Player.prototype
(及其原型,除了Object.prototype
之外的任何属性复制到玩家对象上。不太理想,但功能齐全,这只是意味着您需要确保Player.prototype
在创建第一个播放器之前包含所有内容。此外,instanceof
对玩家无效。只需连接您想要的位,而无需实际使用
socket
作为原型,方法是将绑定函数添加到实际路由到 [=17= 的Player
实例]:var Player = function (socket, x, y) { this.on = socket.on.bind(socket); this.emit = socket.emit.bind(socket); this.x = x; this.y = y; };
然后使用
new
.或者更冗长一点,但如果您需要,可以让您有机会进入中间:
var Player = function (socket, x, y) { this.socket = socket; this.x = x; this.y = y; }; Player.prototype.on = function() { return this.socket.on.apply(this.socket, arguments); }; Player.prototype.emit = function() { return this.socket.emit.apply(this.socket, arguments); };
以上两个都使用了 ES5 中可以填充的特性。从 Socket
、on
和 emit
,我猜你正在使用 NodeJS,所以你正在使用 V8 并且你拥有这些功能。但是,如果不是,以及其他有类似问题的人:第一个解决方案使用 Object.create
的单参数版本,第二个使用 Function#bind
。如果您需要支持较旧的 JavaScript 引擎,只需查找它们的 polyfill,它们都非常小。
术语 inheritance
在 JS 中与其他语言不同。具体来说,很多人一想到inheritance
,就会想到JS中不存在的classical inheritance
。相反,JS 使用 delegation 的概念来对对象进行原型设计,以模拟类似继承的行为。根据您的描述,您似乎希望 Player
的实例具有属于 Socket
的功能。在那种情况下,您所描述的更像是 Player
委托给 Socket
.
下面是一些示例代码:
// assuming you have code that defines what a socket is
var Player = function (x, y) {
var socket = new Socket();
var p = Object.create( socket );
p.x = x;
p.y = y;
return p;
};
Player
的实例现在可以将 属性 查找委托给 socket
实例。
So basically I need to inherit Player from Socket
不,你不知道。继承是一种 是一种 关系,而 Player
可能不是 Socket
。另一方面,它可能会 使用 一个 Socket
实例 - 这种类型的关系可以通过 复合 关系建模。
因此您需要将 Socket
实例注入到您的 Player
构造函数中,以便在生成的 Player
实例中使用 player
.
你在这里试图做的是使用继承来重用代码,多年来这已被证明是一种有缺陷的方法,因为它在父对象和子对象之间引入了紧密的隐式(通常是不需要的)耦合.根据您问题中的信息,组合是可行的方法。