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

您需要决定的第一件事是您想要克隆还是副本,它们是两件不同的事情。

您给出的代码做了一个副本(而不是一个很好的副本,因为使用 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);

可用于实现池。然后,您将用 pool.get() 替换扩展深度函数中的 [] 和 {}。

当然,要使其正常工作,您还需要确保回收旧对象和数组,而不是仅仅将它们留作垃圾收集。

于 2012-11-30T02:13:11.960 回答