簡體   English   中英

將2個javascript對象連接在一起的正確方法是什么?

[英]What is the right way to wire together 2 javascript objects?

我目前面臨一個難題:將兩個javascript對象連接在一起的正確方法是什么?

想象一下像文本編輯器這樣的應用程序,它有幾個不同的文件。 我有一些HTML頁面代表筆記本的視圖。 我有一個文件notebook.js,其中包含NotebookController和Notebook View的類定義。

NotebookControler對象負責在筆記本上執行業務邏輯,如“保存筆記本”,“加載筆記本”,“新筆記本”。 NotebookView負責管理用於演示的HTML。 它做低級別的東西,如“獲取/設置筆記本電腦主體”“獲取/設置筆記本名稱”。 它還偵聽DOM事件(onClick)並觸發業務事件(saveNotebook)。 這是我對被動視圖模式的嘗試。

我希望我的javascript客戶端代碼是面向對象的,分離的關注點和單元可測試的。 我想用模擬NotebookView測試NotebookController,反之亦然。 這意味着我不能只在NotebookController中實例化NotebookView。 我也是

  • 在我的notebook.js中放入一些邏輯,將2連接在一起
  • 在我的應用程序中有一個全局函數,它知道實例化其中一個並將它們連接在一起
  • 使用依賴注入,可以是本土的,也可以是SquirrelIoc

在Java中,選擇是自然的:使用Spring。 但這似乎不是JavaScript-y。 什么是正確的做法?

依賴注入可能是你最好的選擇。 與Java相比,JS代碼中的某些方面更容易實現,因為您可以將一個充滿回調的對象傳遞到NotebookController中。 其他方面更難,因為您沒有靜態代碼分析來形式化它們之間的接口。

感謝您的見解。 我最終編寫了一個簡單的JavaScript依賴注入實用程序。 經過一段時間的辯論和你的評論之后,我發現DI確實是正確答案,因為:

  1. 它完全將布線問題與業務邏輯分開,同時保持布線邏輯接近有線連接。
  2. 它允許我通常在我的對象上提供一個“你全部接線”回調,這樣我就可以進行三階段初始化:實例化所有內容,連接所有內容,調用每個人的回調並告訴他們他們已經連線。
  3. 很容易檢查依賴性缺失問題。

所以這是DI工具:

var Dependency = function(_name, _instance, _dependencyMap) {
    this.name = _name;
    this.instance = _instance;
    this.dependencyMap = _dependencyMap;
}

Dependency.prototype.toString = function() {
    return this.name;
}

CONCORD.dependencyinjection = {};

CONCORD.dependencyinjection.Context = function() {
    this.registry = {};
}

CONCORD.dependencyinjection.Context.prototype = {
    register : function(name, instance, dependencyMap) {
        this.registry[name] = new Dependency(name, instance, dependencyMap);
    }, 
    get : function(name) {
        var dependency = this.registry[name];
        return dependency != null ? dependency.instance : null;
    },

    init : function() {
        YAHOO.log("Initializing Dependency Injection","info","CONCORD.dependencyinjection.Context");
        var registryKey;
        var dependencyKey;
        var dependency;
        var afterDependenciesSet = [];
        for (registryKey in this.registry) {
            dependency = this.registry[registryKey];
            YAHOO.log("Initializing " + dependency.name,"debug","CONCORD.dependencyinjection.Context");

            for(dependencyKey in dependency.dependencyMap) {
                var name = dependency.dependencyMap[dependencyKey];
                var instance = this.get(name);
                if(instance == null) {
                    throw "Unsatisfied Dependency: "+dependency+"."+dependencyKey+" could not find instance for "+name;
                }
                dependency.instance[dependencyKey] = instance; 
            }

            if(typeof dependency.instance['afterDependenciesSet'] != 'undefined') {
                afterDependenciesSet.push(dependency);
            }
        }

        var i;
        for(i = 0; i < afterDependenciesSet.length; i++) {
            afterDependenciesSet[i].instance.afterDependenciesSet();
        }
    }

}

我會說,只需將它們連接在一起:

function wireTogether() {
  var v = new View();
  var c = new Controller();
  c.setView(v);
}

但當然另一個問題提出了 - 你如何測試wireTogether()函數?

幸運的是,JavaScript是一種非常動態的語言,因此您只需為View和Controller分配新值:

var ok = false;

View.prototype.isOurMock = true;
Controller.prototype.setView = function(v) {
  ok = v.isOurMock;
}

wireTogether();

alert( ok ? "Test passed" : "Test failed" );

我有一個javascript控件庫的反轉,我很高興。 https://github.com/fschwiet/jsfioc 它還支持事件,所以如果你想要一個很好的啟動事件。 它可以使用更多文檔......

http://github.com/fschwiet/jsfioc

另一個(較新的?)選項,具有更好的文檔和支持,是requireJS(http://requirejs.org/)。

還有一個用於JavaScript依賴注入的框架: https//github.com/briancavalier/wire

我會嘗試對此進行嘗試,但如果沒有看到任何實際代碼,那將會有點困難。 就個人而言,我從未見過有人在(M)VC上使用JavaScript或IoC進行過這樣的特定嘗試。

首先,你要測試什么? 如果您還沒有,請查看YUI測試視頻 ,其中包含有關使用javascript進行單元測試的一些好信息。

其次,當你說“連接聚合的最佳方式”時,我可能會把它當作一個帶控制器的setter

// Production
var cont = new NotebookController();
cont.setView( new NotebookView() );

// Testing the View
var cont = new NotebookController();
cont.setView( new MockNotebookView() );

// Testing the Controller
var cont = new MockNotebookController();
cont.setView( new NotebookView() );

// Testing both
var cont = new MockNotebookController();
cont.setView( new MockNotebookView() );

但是這對你如何設計控制器和查看對象做了一些很大的假設。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM