window.foo
そのグローバル変数にアクセスします。
this.close=function(){ delete window.foo; }
ただし、グローバル変数、delete、windowには厄介なものがあることを覚えているので、それ以外の方法で、window.foo = null;
たとえば単に使用することをお勧めします。
別の関数で定義された変数にアクセスする場合は、このSOの質問に対する回答を読む必要があります。
必要なのはガベージコレクタがそのオブジェクトを解放できるようにすることなので、オブジェクトへの参照が残っていないことを確認する必要があります。オブジェクトを操作するコードは、グローバル変数とローカル変数、および属性を介してオブジェクトを複数回参照できるため、これは非常に難しい(つまり不可能な)場合があります。
オブジェクトにアクセスするためのプロキシを作成することで、オブジェクトへの直接参照を防ぐことができます。残念ながら、javascriptは動的ゲッターとセッター(キャッチオールとも呼ばれます)を十分にサポートしていません(ただし、一部のブラウザーでは、このSOの質問を参照してください) 、したがって、すべてのフィールドとメソッド(とにかく単なるフィールド)アクセスを基になるオブジェクトに簡単にリダイレクトすることはできません。特に、基になるオブジェクトに多くのフィールドが追加され、動的に削除される場合(つまりthis.anewfield = anewvalue
)。
これがsmipleプロキシ(jsfiddle.netのコード)です:
function heavyobject(destroyself, param1, param2) {
this.id=0;
this.action=function(){alert('tost ' + param1 + "," + param2);};
this.close=function(){ destroyself(); }
}
function proxy(param1, param2) {
object = null;
// overwrites object, the only reference to
// the heavyobject, with a null value.
destroyer = function() { object = null; };
object = new heavyobject(destroyer, param1, param2);
return function(fieldname, setvalue) {
if (object != null) {
if (arguments.length == 1)
return object[fieldname];
else
object[fieldname] = setvalue;
}
};
}
var foo = proxy('a', 'b');
alert(foo("action")); // get field action
foo("afield", "avalue"); // set field afield to value avalue.
foo("action")(); // call field action
foo("close")(); // call field close
alert(foo("action")); // get field action (should be 'undefined').
これは、単一の引数で呼び出されたときにラップされたオブジェクトのフィールドを取得し、2つの引数で呼び出されたときにフィールドを設定する関数を返すことによって機能します。これは、heavyobjectへの唯一の参照が関数内のobject
ローカル変数であることを確認することによってproxy
機能します。
ヘビーオブジェクトのコードは決してリークしてはなりませんthis
(決して返さない、参照を保持する関数を返さないvar that = this
、別の変数のフィールドに格納しない)。そうしないと、ヘビーオブジェクトを指す外部参照が作成され、削除できなくなる可能性があります。
ヘビーオブジェクトのコンストラクターがコンストラクターdestroyself()
内から(またはコンストラクターによって呼び出される関数から)呼び出す場合、効果はありません。
別のより単純なプロキシ。フィールドを追加したり、フィールドを読み取ったり、メソッドを呼び出したりできる空のオブジェクトを提供します。これでは、外部参照を逃れることはできないと確信しています。
コード(jsfiddle.netにもあります):
function uniquelyReferencedObject() {
object = {};
f = function(field, value) {
if (object != null) {
if (arguments.length == 0)
object = null;
else if (arguments.length == 1)
return object[field];
else
object[field] = value;
}
};
f.destroy = function() { f(); }
f.getField = function(field) { return f(field); }
f.setField = function(field, value) { f(field, value); }
return f;
}
// Using function calls
o = uniquelyReferencedObject();
o("afield", "avalue");
alert(o("afield")); // "avalue"
o(); // destroy
alert(o("afield")); // undefined
// Using destroy, getField, setField
other = uniquelyReferencedObject();
other.setField("afield", "avalue");
alert(other.getField("afield")); // "avalue"
other.destroy();
alert(other.getField("afield")); // undefined