0

JavaScript オブジェクト用に DSL のようなビルダーを作成したいのですが、DSL-Builder オブジェクトがガベージ コレクター (作成されたオブジェクト) によって削除されるかどうかわかりません。コードは次のとおりです。

function Section() {...}

Section.DSL = function() {
  var section = new Section();

  return {
    title: function(s) { section.title = s; },         /* Just for example */
    content: function(s) { section.content = s; },     /* Logic has been removed */
    section: section
  }
}

function section(builderFn) {
  var dsl = new Section.DSL();
  fn.call(dsl, dsl);

  return dsl.section;
}

/* Somewhere in the code */
var mySection = section(function(s) { 
  s.title('Hello, my section');
  s.content('We can put it in later');
});

/* I want my DSL object created internally by section method 
   to be removed by garbage collector */

ここでは、Section の新しいインスタンスを初期化し、便利なメソッドを使用してその値を埋めるためだけに DSL を使用します。自分の DSL オブジェクトを破棄したいのですが、そのメンバーの 1 つをさらに使用するとどうなるかわかりません。

たぶん、dsl.sectionをnullに設定するか、「delete dsl.section」を使用して削除する「dispose」メソッドを作成する必要がありますか?その後、私のセクションは DSL から切断され、ガベージ コレクターによって正常に削除され、新しい参照 "mySection" を介して引き続き使用されます。

別のアイデアがあります:

DSL をシングルトンとして使用する可能性があります。その場合、ビルダー関数を呼び出す前に、「セクション」メソッド内に新しいセクション オブジェクトを作成し、それを DSL オブジェクト (シングルトンになります) に割り当てる必要があります。それは良い解決策ですか?例は次のとおりです。

Section.DSL = {
  construct: function(section) {
    this.section = section;
    return this;
  }

  /* Builder methods */
}

function section(builderFn) {
  var section = new Section();

  /*  Imagine that DSL is just an object with a few functions 
      and construct just set its section variable and returns this
   */
  var dsl = Section.DSL(section); **/
  fn.call(dsl, dsl);

  return section;
}
4

1 に答える 1

0

GC はobject-reachabilityのみ考慮します。いずれにせよ、次の例を検討してください。

function f (s) {
  // The variable "s" is a reachability root for the given scope;
  // any object that it names is guaranteed to be reachable
  // as long as the closure(s) below are reachable.
  return {
     getIt: function () { return s }
     setIt: function (_s) { s = _s }
  }
}

例 ケース 1.

g = f({my: "Object"})
// Closures are no longer strongly reachable, and thus the object
// can be reclaimed.
// (Also note there are no other strong references to the object!)
g = null
// Told yah, so, oops exception!
g.getIt()

例のケース 2。

g = f({my: "Object"})
// The variable "s" bound by the closures has been re-assigned and
// thus no longer strongly references the original object;
// the original object is thus eligible for reclamation.
// (Note no other strong references!)
g.setIt(null)
// But of course we just have null now .. oops!
g.getIt().my

例のケース 3。

o = {my: "Object"}
g = f(o)
g.setIt(null)
// ..but the object is NOT eligible for reclamation because it is
// strongly reachable through "o" (which is a reachability root
// in this scope).
alert(o)

さて、興味のある唯一の実際のケース(コメントで逃した)は次のとおりです。

function f2(s) {
   var hash_of_s = hash(s)
   // The variable "s" is not accessed from any closure
   return {
      getHash: function () { return hash_of_s }
   }
}
g = f2(/* some LARGE object currently only reachable here */)
// Is the object referenced by "s" reclaimable here?
alert(g.getHash())

この場合、クロージャーが強力に到達可能であると仮定すると、「s」は初期オブジェクトの到達可能性を維持しますか?

技術的には、「s」が到達可能性を維持していないと実装で判断できますが、Node.js がそれをどのように処理するかは知っています

于 2013-01-29T19:23:32.877 に答える