2012-04-15 114 views
0

我正在研究類似於elFinder的文件管理器框架。我目前的代碼工作正常,但現在我想讓它看起來更好,並添加鏈接(我不知道它是鏈或裝飾模式)。
這種鏈接在JavaScript中可能嗎?

這裏是什麼,我想做一個示例:

function UI() {} 

UI.prototype.folders = function(){ 
    return []; 
} 

UI.prototype.folders.prototype.getSelectedFolder = function(){ 
    return {}; 
} 

調用UI.folders()應該返回文件夾對象的數組。所以,如果你UI.folders()你會得到一些與此類似:

[ 
    Object { name="folder1", selected=false }, 
    Object { name="folder2", selected=false }, 
    Object { name="folder3", selected=true } 
] 

,並呼籲UI.folders().getSelectedFolder()將過濾從UI.folders()結果將返回:

Object { name="folder3", selected=true } 

這可能嗎?在這種情況下說「鏈接」還是「裝飾模式」是正確的?
如果不是 - 是否有另一種更合適的方法來做到這一點?

任何幫助將真正感激!

+1

你沒有正確地進行繼承。 '... folders.prototype.getSelectedFolder'沒有任何好處,因爲'UI.prototype.folders'只返回一個普通數組。爲'folders.prototype'產生效果,你需要調用'folders'作爲構造函數,並讓它返回被構造的對象而不是Array。 – 2012-04-15 17:25:42

+1

...但是,正確實施,'UI.folders()。getSelectedFolder()'是方法鏈接的一個例子。 – 2012-04-15 17:26:43

+1

+1我不確定爲什麼投票反對,這不僅僅是一個很好的描述性問題,而且還包括了你想要做的事情。 – 2012-04-15 17:32:25

回答

0

這是幾種不同的方法來解決這個問題。主要目標是當你調用一個函數時,你會得到一個對象/函數,它是具有不同屬性的相同類型的對象。我不是原型用法的粉絲,所以我會這樣做(這是解決它的一種方式):

var FolderList = function() 
{ 
    var _folders = []; 
    folders.pop({ name: "folder1", selected: false }); 
    folders.pop({ name: "folder2", selected: true }); 
    folders.pop({ name: "folder3", selected: false }); 

    // prevent other programers from changing _folders 
    // which would break this, so just use a function 
    this.folders = function() 
    { 
     return _folders; 
    } 

    this.selectedFolders = function() 
    { 
     var tmpFolders = []; 
     for (var folderIndex = 0; 
      folderIndex < this._folders.length; 
      folderIndex++) 
     { 
      if (this._folders[folderIndex].selected) 
      { 
       tmpFolders.pop(_folders[folderIndex]); 
      } 
     } 
     _folders = tmpFolders; 
     return this; 
    } 

    this.addFolder = function (folder) 
    { 
     _folders.pop(folder); 
     return this; 
    } 
}; 

var folderList = new FolderList(); 
folderList.selectedFolders() 
      .addFolder({ name: "folder1", selected: false }) 
      .addFolder({ name: "folder3", selected: true }) 
      .selectedFolders(); 

// array of 2 objects, folder2 and folder3 
var arrayOfSelectedFolder = folderList.folders(); 
+0

感謝您的代碼!使用你的代碼的一部分我想出來:) – tftd 2012-04-16 22:37:54

1

爲了使這個正常工作,你需要讓你的文件夾,方法是返回,從一個數組:繼承對象的功能

UI.prototype.folders = function(){ 
    // must return an object that inherits from an array 
    // that has the additional methods on it you want like getSelectedFolder() 
} 
2

在你的問題中的代碼是不能反映一個適當的實施,但回答你的直接問題,是的,這...

UI.folders().getSelectedFolder() 

...將是一個方法鏈的例子。


裝飾模式是不同的。如果你有一組方法,每個人應該總是先調用一些常用的功能,你可以創建一個裝飾,將返回首先調用常見的一種,那麼實際的一個功能...

function foo() { 
    console.log('I\'m foo, and I\'m first, and I was given these args:', arguments); 
} 

function decorateWithFoo(decorated) { 
    return function() { 
     foo.apply(this, arguments); 
     decorated.apply(this, arguments); 
    }; 
} 

所以,你可以使用decorateWithFoo創建總是調用foo第一功能...

// create and decorate bar() 
var bar = function(a,b) { 
    console.log('I\'m bar, and I was called after "foo", and was given args:', a, b); 
}; 
bar = decorateWithFoo(bar); 

bar(123, 456); // this will first call `foo()`, then (the original) `bar()`. 

// create and decorate baz() 
var baz = function(a,b) { 
    console.log('I\'m baz, and I was called after "foo", and was given args:', a, b); 
}; 
baz = decorateWithFoo(baz); 

baz(123, 456); // this will first call `foo()`, then (the original) `baz()`. 

一些語言已經建立了用於創建裝飾器的語法。 JavaScript目前沒有。


如果你發現自己使用的裝飾以不同的方式,你可以創建,設置了最初的裝飾功能的其他功能...

function generateDecorator(decorator) { 
    return function (decorated) { 
     return function() { 
      decorator.apply(this, arguments); 
      decorated.apply(this, arguments); 
     }; 
    }; 
} 

所以我們原來decoreateWithFoo可能已經建立了這樣的...

function foo() { 
    console.log('I\'m foo, and I\'m first, and I was given these args:', arguments); 
} 

var decorateWithFoo = generateDecorator(foo); 
+0

感謝您的擴展解釋 - 它清除了一切! – tftd 2012-04-16 22:43:57