8

Nicholas ZakasAddy Osmani的这些谈话中,他们讨论了在构建大型 Javascript 应用程序时使用外观模式作为沙箱的想法,以便将应用程序与底层基础库分离。

这种解耦在理论上允许您切换一个基础库,而无需重写您的应用程序模块。然而在实践中,这似乎更难以实施。

这个提议的架构有具体的实现,例如AuraJS。然而,从查看源代码来看,沙箱似乎仍然通过从它的一些方法返回 jQuery 对象而具有泄漏的抽象。

我并不特别关心 AuraJS,但更多的是尝试抽象像 jQuery 这样的库而不丢失这么多功能的一般概念。

例如,假设我的外观/沙箱有一个 dom 方法.find(selector)。我可以想到它可能返回的 3 个选项:

  1. 一个 jQuery 对象- 这会将 jQuery 泄漏到消费模块中。

  2. 一个原始的 dom 元素- 功能丧失,没有人真正想要使用它!没有连锁。

  3. 一个自定义的类 jQuery 包装器- 可能非常复杂,但似乎是理想的解决方案。

所以我的问题是,你如何在不丢失太多功能的情况下抽象出一个像 jQuery 这样的库,以便在将来的某个时候用最小的努力来替换它?

4

2 回答 2

0

这是一个使用模块作为架构的非常简单的示例:

<!DOCTYPE html>
<title>Module play</title>
<body>
<script>

// myCore provides all functionality required by modules
// Could use a library in here
var myCore = {

  getContainer: function() {
    // code in here to find a suitable container in which to put widgets
    // This is where different client capabilities will be tested to ensure the
    // widget behaves in it's user agent context - desktop, phone, tablet, pad, etc.

    // very simple shortcut
    return {
            element: document.body,

            // This function could use a general purpose library
            add: function(widget) {
              this.element.appendChild(widget.getElement());
            }
    };

  },

  // This function could use a general purpose library
  getNewWidget: function() {
    var element = document.createElement('div');

    return {

      getElement: function() {
        return element;
      },

      display: function(text) { 

        // Tightly couple to itself or not? 
        this.getElement().innerHTML = '<em>' + text + '</em>';

        // or
        element.innerHTML = '<em>' + text + '</em>';
      }
    }
  }
};

// Missing sandbox layer...

// Add a module - only uses myCore API (access should be controlled by
// the sandbox), does not deal with underlying library or host objects
(function() {

  // Get a container to add a widget too
  var container = myCore.getContainer();

  // Create a widget
  var widget = myCore.getNewWidget();

  // Add the widget to the container
  container.add(widget);

  // Give something to the widget to display
  widget.display('Hello World');

}());

</script>
</body>

所以你可以看到,在模块级别,你并不关心宿主环境或底层库,你只是在编写普通的 ECMAScript。你可以得到真正的防守并做一些事情,比如:

(function() {
    var container, widget;

    if (!myCore) return;

    if (myCore.getContainer) { // Some would include an isCallable test too

      container = myCore.getContainer();
    }

    // getWidget could be a method of container instead so that
    // everything you need is either a method or property of container
    // or widget
    if (myCore.getWidget) {
      widget = myCore.getWidget();
    }

    ...
}

依此类推,一切都经过测试和检查。我省略了错误处理,但希望这个例子就足够了。

于 2013-04-17T03:53:14.590 回答
-1

我认为您是在询问是否编写更多模块化代码,但 jquery 不是一个好的案例。

异步模块定义 http://addyosmani.com/writing-modular-js/

于 2013-04-16T09:14:05.123 回答