我正在初始化这样的类(字符是我程序中的一个类):
character = new Character();
我想要这个类/对象的两个实例,所以我尝试了这个:
character2 = new Character();
然而,字符2只是简单地取代了字符;因此,只有一个对象。是否可以创建另一个实例,或者我需要创建另一个 Character 类(大量代码重复!
我尝试为第二个对象添加第二个绘制函数(名为 draw2),但这没有帮助。
您需要将Character.prototype.draw
方法的定义移出构造函数。否则,每次创建new Character()
时,也会重写Character.prototype.draw
方法。
您还需要将Character.prototype.draw
方法中对局部构造函数变量(如x
、y
或size
)的引用替换为对象属性(如this.X
、this.Y
和this.Size
)。
此外,您需要使img
成为Character
的(可能是静态的)属性。
现代 JS 中的对象创建
现代 JS 在定义对象时包含一些快捷方式。除非您要创建对象的许多实例,否则实际上不需要使用原型。使用对象时,访问原型会增加一些开销
您可以在创建函数中创建对象,该函数允许您通过闭包定义私有属性。
关闭创建私有属性
function Character() {
var x = 0;
var y = 0;
var size = 25;
var vx = 4;
var vy = 4;
var width = 45;
var height = 45;
var img = new Image();
img.src = 'character.jpg';
var pattern;
// using API = {rather than return { allows you to access the instance of the
// inside this scope without having to use the `this` token
const API = {
get x() { return x },
get y() { return y },
get vx() { return vx },
get vy() { return vy },
get size() { return size },
get width() { return width },
get height() { return height },
set x(v) { x = v },
set y(v) { y = v },
set vx(v) { vx = v },
set vy(v) { vy = v },
set size(v) { size = v },
set width(v) { width = v },
set height(v) { height = v },
draw(ctx) {
ctx.save();
ctx.translate(x, y);
ctx.lineWidth = 2;
ctx.fillStyle = pattern ? pattern = ctx.createPattern(img, "no-repeat") : pattern;
ctx.beginPath();
ctx.moveTo(-size, -size);
ctx.lineTo(-size, size);
ctx.lineTo(size, size);
ctx.lineTo(size, -size);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
},
}
return API;
}
用法
var char = Character();
var char1 = Character();
// or
var char = new Character();
var char1 = new Character();
性能注意事项
如果性能代码中需要该对象,则可能需要创建性能更高的资源库和 getter,或者避免 getter setter 开销并将属性包含在对象本身中。
function Character() {
var img = new Image();
img.src = 'character.jpg';
var pattern;
// using API = {rather than return { allows you to access the instance of the
// inside this scope without having to use the `this` token
const API = {
x : 0,
y : 0,
size : 25,
vx : 4,
vy : 4,
width : 45,
height : 45,
draw(ctx) {
const size = API.size;
ctx.save();
ctx.translate(API.x, API.y); // Note that I use API.x rather than this.x
ctx.lineWidth = 2;
ctx.fillStyle = pattern ? pattern = ctx.createPattern(img, "no-repeat") : pattern;
ctx.beginPath();
ctx.moveTo(-size, -size);
ctx.lineTo(-size, size);
ctx.lineTo(size, size);
ctx.lineTo(size, -size);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
},
}
return API;
}
笔记。
我注意到你的评论太多了。
例如
//public property for VX
Object.defineProperty(this, 'width',
和
//function public draw method
Character.prototype.draw = function (ctx) {
//save the ctx
ctx.save();
//set x and y
ctx.translate(x, y);
//set the line width
ctx.lineWidth = 2;
你在评论中陈述了显而易见的事情,没有机器会阅读它,没有人需要阅读它,那么为什么它在那里。注释会增加噪音,源代码噪音很危险,请避免代码中所有不必要的噪音。
每次调用 draw 函数时都会创建模式,这是不必要的开销。仅创建一次。
有时调用绘制函数可能不起作用,因为图像尚未加载。也许您应该管理对象之外的图像,在那里您可以确保媒体对象已加载并准备好使用,因为您尝试使用它们。
Character
的每个实例将加载映像,创建 100 个映像,并且同一映像将有 100 个副本。这将对性能和内存产生负面影响。