将局部变量释放到窗口范围变量?

时间:2013-06-16 15:51:37

标签: javascript

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

NS.some_func();

使用名为extendSafe()

的方法填充NS
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;
                    }
                }
            });
        }
    };

1 个答案:

答案 0 :(得分: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的引用。它真的调用了函数吗?在较小的例子中,这只是一个错字吗?

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