在Javascript中,当执行深层复制时,如何避免循环,因为属性为“this”? [英] In Javascript, when performing a deep copy, how do I avoid a cycle, due to a property being "this"?

查看:115
本文介绍了在Javascript中,当执行深层复制时,如何避免循环,因为属性为“this”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些库代码在我身上无休止地循环。

I have some library code that is cycling endlessly on me.

我不清楚如何在javascript中最好地执行循环检测和避免。
即没有以编程方式检查对象是否来自this引用,是吗?

I'm not clear on how to best perform cycle detection and avoidance in javascript. i.e. there's no programmatic way of inspecting whether an object came from a "this" reference, is there?

这是代码。
谢谢!

Here's the code. Thanks!

setAttrs: function(config) {
    var go = Kinetic.GlobalObject;
    var that = this;

    // set properties from config
    if(config !== undefined) {
        function setAttrs(obj, c) {
            for(var key in c) {
                var val = c[key];

                /*
                 * if property is an object, then add an empty object
                 * to the node and then traverse
                 */
                if(go._isObject(val) && !go._isArray(val) && !go._isElement(val)) {
                    if(obj[key] === undefined) {
                        obj[key] = {};
                    }
                    setAttrs(obj[key], val);  // <--- offending code; 
                                              // one of my "val"s is a "this" reference
                                              // to an enclosing object
                }


推荐答案

我所知道的处理这种情况的可靠而干净的方法是使用访问过的对象的集合然后响应 - 终止,插入符号引用等 - 基于当前对象是否已被访问。

The "reliable and clean" way I know of to deal with this situation is to use a collection of "visited" objects and then react -- terminate, insert symbolic reference, etc -- based on if the current object has already been "visited" or not.

先生。 Crockford在 cycle.js 中使用此方法,并使用数组为集合。摘录:

Mr. Crockford uses this approach in cycle.js and he uses an Array for the collection. Excerpt:

// If the value is an object or array, look to see if we have already
// encountered it. If so, return a $ref/path object. This is a hard way,
// linear search that will get slower as the number of unique objects grows.

for (i = 0; i < objects.length; i += 1) {
    if (objects[i] === value) {
        return {$ref: paths[i]};
    }
}

遗憾的是,不可能使用原始的哈希 在JavaScript中实现这一点,因为它缺少Identity-Map。虽然Array-collection边界是 O(n ^ 2),但并没有听起来那么糟糕

It is unfortunately not possible to use a primitive "Hash" approach for this in JavaScript because it lacks an Identity-Map. While the Array-collection bounds are O(n^2) this is not as bad as it sounds:

这是因为,如果visited集合只是一个守护者,那么 n 的值就是堆栈的深度:只有周期才是多次复制同一对象时的重要性不是。也就是说,访问集合中的对象可以在堆栈展开时进行修剪。

This is because, if the "visited" collection is just a guard then the value of n is just the depth of the stack: only cycles are of importance while copying the same object multiple times is not. That is, the objects in the "visited" collection can be pruned on stack-unwind.

在cycle.js代码中,已访问集合无法修剪,因为它必须确保始终使用给定对象的相同符号名称,这允许序列化在恢复时维护引用。但是,即使在这种情况下, n 遍历的唯一非原始值的数量。

In the cycle.js code the "visited" collection cannot be pruned because it must ensure the same symbolic name for a given object is always used which allows the serialization to "maintain the references" when it is restored. However, even in this case, n is only the number of unique non-primitive values traversed.

我能想到的唯一其他方法是需要将访问属性直接添加到被遍历的对象,我认为这通常是不受欢迎的特性。 (但是,请参阅Bergi关于这个神器被[相对]轻松清理的评论。)

The only other method I can think of would require adding a "visited property" directly to the objects being traversed, which I would consider a generally undesirable feature. (However, see Bergi's comment about this artifact being [relatively] easily cleaned up.)

快乐编码。

这篇关于在Javascript中,当执行深层复制时,如何避免循环,因为属性为“this”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆