2009-01-08 95 views
0

我正在創建一個小代碼插件,它允許你用數組做一些事情。我不希望將功能添加到使用原型建造的數組對象,我要的是,人們可以這樣做:

arrayFunction([1, 2, 3]).someSpecialArrayFunction(); 

因此離開正常的數組對象不變。
於是我想出了下面的結構(這是啓發了jQuery源代碼):

var arrayFunction = window.arrayFunction = function(array) { 
    return new arrayFunction.fn.init(array); 
} 
arrayFunction.fn = arrayFunction.prototype = { 
    init: function(array){ 
     this.a = array; 
     //should I return something here? 
    }, 
    someSpecialArrayFunction: function(){ 
     //Super cool custom stuff here. 
    } 
} 

然而,這並不工作(明顯)。 init函數()中應該發生什麼?

錯誤現在的問題是,當我嘗試:

arrayFunction(array).someSpecialArrayFunction(); 

它說,someSpecialArrayFunction()不是一個功能?

應該怎麼做?

編輯
是的,這確實是一個簡單的例子。實際的東西有更多的方法。

另外,我只是雖然它會是多麼令人敬畏,如果它也支持chaning,你會怎麼做?

+0

jquery的$實際上是一個對象。 – Malfist 2009-01-08 17:57:24

+0

在Javascript中,所有函數都是對象 - 您實際上是使用function關鍵字聲明對象的,因此jQuery $既是對象又是函數,它返回該對象的實例。這可能需要一些習慣... – 2009-01-08 18:21:55

+0

你在這裏尋找一種方法來創建你的示例*工作* - 或者通過將方法添加到包裝器的原型中來將方法附加到包裝器對象的一般模式。所以你可以管理大量的擴展方法集合? – 2009-01-08 18:47:18

回答

2

或者乾脆:

var arrayFunction = function(array) { 
    var someSpecialArrayFunction = function() { 
     // do something with array 
    }; 
    return { 
     someSpecialArrayFunction: someSpecialArrayFunction 
    } 
}; 
arrayFunction([1, 2, 3]).someSpecialArrayFunction(); 

雖然要小心這個,如果你最終會有太多的方法可能會更好地使用原型。

1

我不知道這是爲了得到你想要的最好的語法,但我想這是一個下調例子...反正這裏是一個快速的方法,使工作

var arrayFunction = window.arrayFunction = function(array) { 
    return new arrayFunction.fn.init(array); 
} 
arrayFunction.fn = arrayFunction.prototype = { 
    init: function(array){ 
     var a = array; 
     return { 
      someSpecialArrayFunction: function(){ 
       alert (a.join(' - ')); //Super cool custom stuff here. 
      } 
     }; 
    }, 
} 
arrayFunction([1, 2, 3]).someSpecialArrayFunction(); 
0

sktrdieanswer看起來不錯。

要考慮的另一件事是使用flyweight pattern而不是每次調用您的包裝時都返回一個新的對象實例。 ExtJS功能Ext.fly這樣做;它會返回一個全局共享的實例。

0

嘗試這樣:

var mathWrapper = function(array) { 
    return { 
     mean : function(){ 
      if (array.length == 0) return(0); 
      var total = 0; 
      for (var i = 0; i < array.length; i++) total += array[i]; 
      return(total/array.length); 
     }, 
    }; 
} 

通過調用的東西像

document.write(mathWrapper([1,2,3,4,5,6]).mean()); 

應該返回數組元素的平均值。

0

如果你不想T改變Array.prototype,唯一真正可行的解決方案是增加的方法,具體的數組對象:

function doSomething() {} 
function doOther() {} 

function wrap(array) { 
    array.doSomething = doSomething; 
    array.doOther = doOther; 
    return array; 
} 

請注意,我不定義doSomething()和內wrap()doOther() - 否則,我們會在每次調用時創建新的函數對象,效率非常低。

一個更復雜的變體將是以下幾點:

function doSomething() {} 
function doOther() {} 

function wrap(array) { 
    if(this instanceof arguments.callee) { 
     this.doSomething = doSomething; 
     this.doOther = doOther; 
    } 
    else { 
     arguments.callee.prototype = array; 
     return new arguments.callee; 
    } 
} 

在這裏,我們創建了一個新的包裝對象(不屬性陣列自身添加)。包裝器對象仍然可以訪問所有數組的屬性。有一個細微差別,但:

var foo = wrap([1,2,3]); 
document.writeln(foo.length); // writes 3 
foo.push(4); 
document.writeln(foo.length); // writes 4 in FF, 3 in IE 
foo[4] = 5; 
foo[5] = 6; 
document.writeln(foo.length); // still writes 4?! 

使用foo[4] =將訪問我們的包裝對象和屬性45將在陣列中設置有與沒有 - 因此,它的長度屬性將不會被更新。在IE中,調用push()將無法​​正確更新陣列...

如果您的包裝器對象不需要將調用重新路由到數組對象,則還有其他解決方案使用閉包--sktrdie的第一個示例是一個這些。我會反對他們,因爲他們會在每次調用時創建新的函數對象。我會做什麼:

function wrap(array) { 
    if(this instanceof arguments.callee) 
     this.array = array; 
    else return new arguments.callee(array); 
} 

wrap.prototype.doSomething = function() {}; 
wrap.prototype.doOther = function() {}; 

在這裏,你可以通過this.arraydoSomething()doOther()訪問陣列。

0

只需擴展Array對象並將您喜歡的方法添加到您的對象。然後,您可以創建一個橋接函數,將數組作爲參數並返回您的數組版本。這種方法要容易得多,也更有用。

相關問題