1

GC用にガベージを作らないextendDeep()関数を作りたいです。

ガベージ コレクタは、できるだけ非アクティブにする必要があります。参照: https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

これは、変更したいextendDeep()関数です。

function extendDeep(parent, child) {
    var i, toStr = Object.prototype.toString,
        astr = "[object Array]";

    child = child || {};

    for (i in parent) {
        if (parent.hasOwnProperty(i)) {
            if (typeof parent[i] === 'object') {
                child[i] = (toStr.call(parent[i]) === astr) ? [] : {};
                extendDeep(parent[i], child[i]);
            } else {
                child[i] = parent[i];
            }
        }
    }
    return child;
}

関数は何も返す必要はありません。返されたオブジェクトがガベージが作成される理由であるためです。

親オブジェクトのすべてのプロパティが参照 (オブジェクトの再利用) によって利用可能であると想定されます。

4

3 に答える 3

1

JS インタープリターは実行時に文字列の作成を回避するtoStr.call(parent[i])場合がありますが、その最適化を実行することに依存できない場合は、変更することで非常に一般的なケースで文字列の作成を回避できます。

toStr.call(parent[i]) === astr

parent[i] instanceof Array  // Is a regular array.
|| (!(parent[i] instanceof Object)  // Is cross-frame
    && 'number' === typeof parent[i].length  // Might be an array
    && toStr.call(parent[i]) === astr)  // So check the hidden [[Class]] property.

同じフレームのコンストラクターによって作成されたオブジェクトを扱っていることがわかっている場合 (つまり、クロスフレーム オブジェクトの共有がない場合) は、

parent[i] instanceof Array
于 2012-11-30T01:39:42.180 に答える
0

最初に決定する必要があるのは、クローンとコピーのどちらが必要かということです。これらは2つの異なるものです。

指定したコードはコピーを実行します(hasOwnPropertyを使用すると、機能しないコピーが簡単に作成される可能性があるため、優れたコードではありません)。クローンは次のようになります。

function Clone(){}
function clone(object) {        
    Clone.prototype = object;

    return new Clone();
}

var objectToClone = {};
var clonedObject = clone(objectToClone);

違いは、コピーの場合、元のオブジェクトを変更してもコピーには影響しないということです。クローンの場合、クローンがプロパティを上書きしない限り、元のオブジェクトへの変更はクローンに影響します。

于 2012-11-30T01:34:17.427 に答える
0

これは実際、私が最初に考えたよりも興味深い質問です。提案されたリンクを読んだ後、記事の著者がオブジェクト プーリングを提唱していることは明らかです。だから何か

function Pool(fConstructor, nMaxSize, fCleanFunction) {
    this.aObjectPool = [];
    this.nMaxSize = nMaxSize;
    this.fCleanFunction = fCleanFunction;
    this.fConstructor = fConstructor;
}

Pool.prototype.get = function() {
    return this.aObjectPool.pop() || new this.fConstructor();
}

Pool.prototype.recycle = function(oObject) {
    if (aObjectPool.length < this.nMaxSize) {
        fCleanFunction(oObject);
        this.aObjectPool.push(oObject);
    }
}       

function wipeArray(aArray) {
    aArray.length = 0;
}

function wipeObject(oObject) {
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            delete obj[p];
        }
    }
};

var oArrayPool = new Pool(Array, 50, wipeArray);

var oObjectPool = new Pool(Object, 50, wipeObject);

プールの実装に使用できます。次に、extend deep 関数の [] と {} を pool.get() に置き換えます。

もちろん、これが機能するためには、古いオブジェクトや配列を単にガベージ コレクションに残すのではなく、リサイクルしていることを確認する必要もあります。

于 2012-11-30T02:13:11.960 に答える