最终,JS 将具有内置的代理功能,它将对后台发生的各种事情进行低级访问,永远不会暴露给前端开发人员(除了通过代理 - - 想想 PHP 等语言中的魔法方法。
那时,只要跨平台 100% 保证支持销毁/垃圾收集作为触发器,在您的对象上编写一个使计数器递减的析构函数方法可能完全是微不足道的。
目前可靠地做到这一点的唯一方法可能是创建一个包含所有已创建实例的封闭注册表,然后手动销毁它们(否则,它们将永远不会被垃圾收集)。
var Obj = (function () {
var stack = [],
removeFromStack = function (obj) {
stack.forEach(function (o, i, arr) {
if (obj === o) { arr.splice(i, 1); }
makeObj.count -= 1;
});
};
function makeObj (name) {
this.sayName = function () { console.log("My name is " + this.name); }
this.name = name;
this.explode = function () { removeFromStack(this); };
stack.push(this);
makeObj.count += 1;
}
makeObj.checkInstances = function () { return stack.length; };
makeObj.count = 0;
return makeObj;
}());
// usage:
var a = new Obj("Dave"),
b = new Obj("Bob"),
c = new Obj("Doug");
Obj.count; // 3
// "Dave? Dave's not here, man..."
a.explode();
Obj.count; // 2
a = null; // not 100% necessary, if you're never going to call 'a', ever again
// but you MUST call explode if you ever want it to leave the page's memory
// the horrors of memory-management, all over again
这个模式会做你想做的事吗?
只要:
- 你不会把
a 变成别的东西
- 不要覆盖它的
explode 方法
- 你不要以任何方式惹
Obj
- 您不希望任何
prototype 方法可以访问任何内部变量
...那么是的,这种方法可以很好地让计数器正常工作。
您甚至可以编写一个名为recycle 的通用方法,它调用您传递给它的任何对象的explode 方法(只要它的构造函数或工厂支持这样的事情)。
function recycle (obj) {
var key;
obj.explode();
for (key in obj) { if (obj.hasOwnProperty(key)) { delete obj[key]; } }
if (obj.__proto__) { obj.__proto__ = null; }
}
注意 - 这实际上不会摆脱对象。
您只需将其从闭包中移除,并移除它曾经拥有的所有方法/属性。
所以现在它是一个空壳,你可以重复使用它,在回收它的部分后明确设置为null,或者让它被收集并忘记它,知道你删除了必要的引用。
这有用吗?
应该不会吧。
我真正认为这是有用的唯一一次是在游戏中,您的角色可能一次只能发射 3 发子弹,并且在屏幕上的第 1 发击中某人之前他不能射击第 4 发或者越界(这就是,比如说,魂斗罗在白天的工作方式)。
您也可以将“消失”的子弹从堆栈中移出,然后通过重置其轨迹、重置适当的标志并将其推回堆栈来为任何玩家/敌人重复使用该子弹。
但是,在代理允许我们定义“神奇”的构造函数/析构函数方法之前,这些方法在低级别得到尊重,这仅在您要对所有自己的对象的创建和销毁进行微观管理时才有用(真的不是一个好主意)。