1

我有一个全局变量 NS ,我可以从控制台访问它:

NS.some_func();

NS 是使用一种名为的方法填充的extendSafe()

some_scope.extendSafe = function (o1, o2) {
    var key;
    for (key in o2) {
        if (o2.hasOwnProperty(key) && o1.hasOwnProperty(key)) {
            throw "naming collision: " + key;
        }
        o1[key] = o2[key];
    }
    return o1;
};

这是通过设置一个名为的公共范围,然后在定义了所有 $P 方法$P后复制到全局范围来使用的。NS

我想这样,这样我就可以验证我没有写任何属性。

在我尝试将局部变量保存到$P以后复制到NS. 因为解释器不知道 $P 将被“释放”到窗口范围,所以它不知道保持局部变量处于活动状态。所以我不能使用我的 safeExtend 方法。

我通过直接复制来验证这是问题所在:

NS.local = local;

我现在可以从控制台访问 NS.local。

但是,如果我按照自己的意愿复制它:

$P.local = local;
extendSafe(NS, $P);

局部变量不可用。

我怎样才能安全地释放它,即使用safeExtend()

代码片段

问题被评论为

// hacked needs a fix

    $P.machine = function (obj) {
        var pipe,
            data_send,
            ajax_type,
            wait_animation,
            set;
        wait_animation = document.getElementById('wait_animation');
        set = false;
        pipe = NS.makePipe(obj);
        if ($R.Parsel[pipe.model] === undefined) {
            return;
        }
        time('start');
        if ($R.Parsel[pipe.model].hasOwnProperty("pre")) {
            pipe = $R.Parsel[pipe.model].pre(pipe);
        } else {
            return;
        }
        if (pipe.form_data) {
            ajax_type = 'multi';
            var form_data = pipe.form_data;
            delete pipe.form_data;
            form_data.append("pipe", JSON.stringify(pipe));
            data_send = form_data;
        } else {
            ajax_type = 'post';
            data_send = 'pipe=' + encodeURIComponent(JSON.stringify(pipe));
        }
        if (pipe.state === true) {
            time('middle');
            if (wait_animation) {
                set = true;
                wait_animation.style.opacity = 1;
            }
            NS.ajax({
                type:     ajax_type,
                url:      NS.Reg.get('path') + NS.Reg.get('path_ajax'),
                data:     data_send,
                callback: function (pipe_string_receive) {
                    var pass_prefix = pipe_string_receive.slice(0, 3),
                        times;
                    if (wait_animation && set) {
                        wait_animation.style.opacity = 0;
                    }
                    if (pass_prefix === '|D|') {
                        NS.log('|DEBUG| ' + pipe_string_receive.slice(3));
                    } else if (pass_prefix === '|A|') {
                        time('middle');
                        pipe = JSON.parse(pipe_string_receive.slice(3));
                        if ($R.Parsel[pipe.model].hasOwnProperty("post")) {
                            pipe = $R.Parsel[pipe.model].post(pipe);
                            times = time('finish');
                            pipe.time.pre = times[0];
                            pipe.time.transit = times[1];
                            pipe.time.post = times[2];

                            // works but hacked needs a fix

                            NS.last = pipe;

                            // will not exendSafe()

                            $P.last = pipe;

                        } else {
                            return;
                        }
                    } else {
                        throw "<No 'A' or 'D'>" + pipe_string_receive;
                    }
                }
            });
        }
    };
4

1 回答 1

1

我看到你已经解决了这个问题,但我感觉你对 JavaScript 有一些误解:

在我尝试将局部变量保存到 $P 以便以后复制到 NS 之前,这一直很好。因为解释器不知道 $P 将被“释放”到窗口范围,所以它不知道保持局部变量处于活动状态。所以我不能使用我的 safeExtend 方法。

我通过直接复制来验证这是问题所在:

NS.local = local;

我现在可以从控制台访问 NS.local。

但是,如果我按照自己的意愿复制它:

$P.local = local;
extendSafe(NS, $P);

局部变量不可用。

我怎样才能安全地释放它,即使用safeExtend()?

这没有意义。JavaScript 非常擅长跟踪对对象的引用。如果有对对象的任何引用,它不会垃圾收集该对象。我不知道“将对象释放到窗口范围”可能意味着什么。实际上没有任何这样的概念,只有对象和对它们的引用。

我尝试查看您的原始代码,但那里有很多与问题无关的代码。如果您要将其简化为最小的测试用例,我敢打赌,一个更简单的解决方案将变得显而易见。

我确实在上面的小片段中看到了一个问题。您将extendSafe()函数定义为some_scope.extendSafe(),但在这里您使用普通extendSafe()调用而不引用some_scope. 它真的调用了这个函数吗?这只是较小示例中的错字吗?

当然,如果您只是很高兴找到了解决方案并想继续前进,那是可以理解的!我只是有一种强烈的感觉,这里有你不需要的额外代码。

于 2013-06-16T18:10:12.340 回答