我想创建一个带有一些隐藏(使用闭包)变量的对象,以及利用这些隐藏变量的方法。但是,我不想为每个实例化重新创建这些方法。我想把它们放在记忆中一次。我正在使用普通函数来实例化对象。
以下是一些代码:
function Mario () {
var mario = {}; // create the obj
mario.name = "Mario"; // create a property on it
mario.hp = (function () { // set up a closure
var currentHp = Mario.baseHp * 100; // create a "hidden" variable
return function (value) { // return the hp function that utilizes the hidden currentHp variable
if (!!value) {
return currentHp = ((currentHp * Mario.baseHp) + value);
}
return currentHp * Mario.baseHp;
};
}());
return mario; // send along the newly created object
}
Mario.baseHp = 1;
var mario = Mario();
log(mario);
log(mario.hp());
log(mario.hp(-20));
log(mario.hp());
这里的问题是每次我创建另一个“mario”对象时,我都会在内存中再次创建hp函数。这是我到目前为止尝试解决的问题:
function Mario () {
var mario = {}; // create the obj
mario.name = "Mario"; // create a property on it
mario.hp = (function () { // set up a closure
var currentHp = Mario.baseHp * 100; // create a "hidden" variable
return Mario.hp; // reference the hp function below..... but the context is wrong, it needs access to currentHp variable.
}());
return mario; // send along the newly created object.
}
Mario.baseHp = 1;
Mario.hp = function (value) { // Create the hp function once in memory
if (!!value) {
return currentHp = ((currentHp * Mario.baseHp) + value);
}
return currentHp * Mario.baseHp;
};
var mario = Mario();
log(mario);
log(mario.hp());
log(mario.hp(-20));
log(mario.hp());
但显然Mario.hp的背景是错误的。我想可能有一种方法可以使用调用或应用来解决这个问题。任何帮助都会摇滚!
答案 0 :(得分:3)
通常的解决方案是使用原型和新的:
function Mario () {
this.name = "Mario"; // create a property on it
this.baseHP = 33;
}
Mario.prototype.hp = function () {
var currentHP = this.baseHp * 100;
...
};
var mario = new Mario();
log(mario);
log(mario.hp());
log(mario.hp(-20));
log(mario.hp());
这会创建通常称为类Mario
的东西。使用new Mario()
创建此classe的实例,所有这些实例都使用相同的函数hp
(函数中的this
引用实例)。
编辑
如果您想存储currentHP
变量和hp
函数以返回它,只需执行以下操作:
function Mario () {
this.name = "Mario"; // create a property on it
this.baseHP = 33;
this.currentHP = this.baseHp * 100;
}
Mario.prototype.hp = function () {
return this.currentHP;
};
var mario = new Mario();
log(mario);
log(mario.hp());
答案 1 :(得分:1)
var Mario = (function() {
var name = "Mario";
var hp = function (value) {
var currentHp = baseHp * 100;
if (!value) {
return currentHp = ((currentHp * Enemy.baseHp) + value);
}
return currentHp * Enemy.baseHp;
}
return {
name:name,
hp:hp
}
})();
console.log(Mario);
console.log(Mario.hp());
console.log(Mario.hp(-20));
console.log(Mario.hp());
我没有对你正在做的其他事情的有效性提出任何要求,因为似乎有很多变量显示但没有考虑,但是你的封闭似乎是在错误的地方。
答案 2 :(得分:1)
我认为所有关于原型的讨论都是过度的,并不是真的对你的情况有帮助。您在这里并不需要原型,因为Mario
的所有实例都将拥有currentHp
的值。同样,您不需要使Mario
成为真正的构造函数,并且担心必须记住new
关键字(尽管您可以根据需要)。
据我所知,您尝试做的所有事情都可以通过闭包来处理,还有一个额外的好处,就是让您的私人成员(如baseHP
和您计算HP的逻辑)真正私密。试试这个:
var Mario = (function () {
//"private" variable encapsulated by the closure
var baseHp = 1;
//"private" method for calculating HP given an instance's current HP
var getHp = function (currentHp, value) {
return currentHp * Enemy.baseHp + (value || 0);
};
//in OOP terms, baseHp and getHp would be like private static members used by
//the whole class.
return function () {
//another "private" variable, but this one is only for
//the current instance.
var currentHp = baseHp * 100;
//instance:
return {
name: "Mario",
hp: function (value) {
return !!value
? currentHp = getHp(currentHp, value)
: getHp(currentHp);
}
};
};
})();
我在控制台中对此进行了测试,看起来效果很好:
//test
var Enemy = {
baseHp: 3
};
var log = console.log.bind(console);
var mario = Mario(); //or new Mario(); either one is fine
log(mario);
log(mario.hp());
log(mario.hp(-20));
log(mario.hp());
在jsFiddle上试试:http://jsfiddle.net/jmorgan123/zkw2P/