【问题标题】:Overwriting JS function by switching files通过切换文件覆盖JS函数
【发布时间】:2012-05-18 02:42:11
【问题描述】:

我知道,一旦脚本加载完毕,您可以从页面中删除 <script> 元素,变量/函数仍将存在。

假设我有两个版本的函数,处理 UI,用户可以根据偏好在其中进行选择。

整个页面大量基于 AJAX。理想情况下,除非用户明确完成,否则它永远不应重新加载,因此调用location.reload() 是不可能的。

我的想法是这样的:

<script type="text/javascript" src="ui1.js" id="uiscript"></script>

然后简单地改变:

document.getElementById('uiscript').src = ...;

两个文件的格式为:

var ui = function(...) {
    ...
};

所以我的问题是,在两个来源之间切换会可靠地改变功能吗?即使脚本被缓存了?我会更好地添加一个 cachebusting 查询字符串吗?还是我应该完全放弃这个想法而去做其他事情,例如在回调中重写函数而不是更改脚本的源代码?

还有其他类似的建议吗?

【问题讨论】:

  • 这是用于生产站点还是仅用于测试工具?我正在使用 iframe 来保存脚本并重新加载 iframe。但这只是一个开发工具。
  • 制作网站 - 更准确地说是游戏。
  • 真的需要切换文件吗?是否有这么多脚本,您不能同时加载/全部并使用类似策略模式的东西来允许用户切换?

标签: javascript ajax user-interface overriding


【解决方案1】:

为什么不使用对函数的引用?这里有一些伪代码:

function func1() { /* Do stuff one way */}
function func2() { /* Do stuff the other way */}
var ui = func1;

ui(some_param);

function myCallback() {
  // overwrite ui
  ui = func2;
  ui(some_param); // now calls func2
}

这只是一个简单的例子。在现实世界中,您会使用 Objects 将您的功能组合在一起。

也许你可以为 JavaScript 使用依赖注入框架,例如 inject

【讨论】:

  • 嗯,这不是一个坏主意。我刚刚运行了一些测试,只是切换脚本的src 不会导致它加载新脚本,所以我想我会选择这个选项。
【解决方案2】:

基本上,您尝试做的只是不好的做法 - 尝试用另一个版本覆盖一个 JS 版本。不要那样做。

如果你有一个函数的两个版本,那么给它们不同的函数名称,并将一个变量设置为活动的,然后使用该变量执行当前函数,如下所示:

function drawMethodOne() {}
function drawmethodTwo() {}
var currentDrawMethod = drawMethodOne;

然后,在您的代码中,您将使用 currentDrawMethod:

currentDrawMethod();

作为对您问题的更具体的回答,javscript 不会卸载以前加载的函数定义。加载更多重新定义现有函数名称的脚本只会将新函数分配给该现有名称,从而使先前函数的代码无法访问。因此,可以通过加载重新定义该函数名称的新 javascript 来替换以前的函数定义,但这通常是一种不好的做法,我可以想到许多调试会非常痛苦的情况。

【讨论】:

    【解决方案3】:

    作为一个快速测试,chrome 在更改源代码时甚至没有尝试为我加载第二个脚本。添加一个新的脚本元素似乎会拉入第二个 js 文件并覆盖该函数。如果这两个函数永远不会改变,您可能希望缓存它们并将“ui”变量重新分配给您需要的任何函数。我同意上面的不良做法 cmets,但我不知道您的用例。

    【讨论】:

      【解决方案4】:

      坦率地说,我不能对这种行为说太多 - 据我所知,它只是不可预测且依赖于实现。一个更好的主意是使用类似下面的东西:

      // usage: call skinHandler.setSkin({/* a skin object */)
      // now having set the skin, call the skin's functions using skinHandler.skin.MyFunc();
      app.skinHandler = function() {
          var oldSkin = null;
          this.skin = null;
          // call this after loading the skin object.
          this.setSkin = function(skin) {
              oldSkin = this.currentSkin;
              this.skin = skin;
          };
      };
      

      皮肤对象将包含您需要的所有用户界面代码,并且因皮肤而异。现在,要使用它,您需要将每个皮肤/主题文件的功能包装在一个单独的对象中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多