2012-02-10 18 views
0

是否有JavaScript模塊可以輕鬆地將參數映射到參數?這是我如何設想它的工作:用於可選/默認參數的輕量級JavaScript模塊

變種參數= assignArguments(自變量, 'P1', 'P2',[{ 'P3':0}, 'P4'],{ 'P5':'未知'});

在一個函數中,您可以調用它來生成一個將參數與參數關聯的對象。在數組或內聯對象中定義的參數將被視爲可選參數,其中內聯對象允許分配默認值。所有其他參數都被認爲是「必需的」。

下面是一些示例輸入/ outpus:

foo(1): { p1: 1, p3: 0, p5: 'unknown' } // no p2 (aka undefined) 
foo(1, 2): { p1: 1, p2: 2, p3: 0, p5: 'unknown' } 
foo(1, 2, 3): { p1: 1, p2: 2, p3: 0, p4: 3, p5: 'unknown' } 
foo(1, 2, 3, 4): { p1: 1, p2: 2, p3: 3, p4: 4, p5: 'unknown' } 
foo(1, 2, 3, 4, 5): { p1: 1, p2: 2, p3: 3, p4: 4, p5: 5 } 

我希望像這樣的庫已經存在。這個邏輯重複了很多,如果可能的話我想消除它。

有沒有人知道這樣的圖書館?如果不是的話,有人可以派我實施一個正確的道路嗎?

+1

我只是使用這個已經實現的coffeescript。 – akonsu 2012-02-10 15:33:24

回答

0

我繼續前進,想到了自己做這個的方法。它涉及解析由字符串,數組和對象組成的對象圖。這很長,但效果很好。

function assignArguments(values, expression) {    
    // determine how many arguments are needed for each parameter 
    // grab all of the defaults, too 
    var needed = 1; 
    var argsNeeded = {}; 
    var defaults = {}; 
    var queue = [expression];    
    for (var queueIndex = 0; queueIndex < queue.length; ++queueIndex) { 
     var node = queue[queueIndex]; 
     if (typeof node === 'string') { 
      // the node is a required parameter 
      argsNeeded[node] = needed; 
      ++needed; 
     } else if (node instanceof Array) { 
      // the node is a list of parameters 
      for (var index = 0; index !== node.length; ++index) { 
       queue.push(node[index]); 
      } 
     } else { 
      // the node is a list of optional parameters with defaults 
      // make sure there isn't more than one parameter 
      var count = 0; 
      for (var key in node) { 
       if (node.hasOwnProperty(key)) { 
        if (count !== 0) { 
         throw new Error('A default parameter list had more than one value.'); 
        } 
        defaults[key] = node[key]; 
        queue.push(key); 
        ++count; 
       } 
      } 
     } 
    } 

    // determine the order that the parameters appear 
    var parameters = []; 
    var stack = [expression]; 
    while (stack.length > 0) { 
     var node = stack.pop(); 
     if (typeof node === 'string') { 
      // the node is a required parameter 
      parameters.push(node); 
     } else if (node instanceof Array) { 
      // the node is a list of parameters 
      var index = node.length; 
      while (index !== 0) { 
       --index; 
       stack.push(node[index]); 
      } 
     } else { 
      // the node is an optional parameter with defaults 
      // we'll check for multiple parameters 
      var count = 0; 
      for (var key in node) { 
       if (node.hasOwnProperty(key)) { 
        if (count > 0) { 
         throw new Error('A default parameter list had more than one value.'); 
        } 
        stack.push(key); 
        ++count; 
       } 
      } 
     } 
    } 

    var result = {}; 
    var valueIndex = 0; 
    for (var index = 0; index !== parameters.length; ++index) { 
     var parameter = parameters[index]; 
     var needed = argsNeeded[parameter]; 
     if (needed > values.length) { 
      if (parameter in defaults) { 
       result[parameter] = defaults[parameter]; 
      } 
     } else { 
      result[parameter] = values[valueIndex]; 
      ++valueIndex; 
     } 
    } 

    return result; 
} 

這裏是一個使用它的例子。

function foo() { 
    var params = assignArguments(arguments, ['p1', 'p2', [{p3:0}, 'p4'], {p5: 'unknown'}]); 
    return params; 
} 

console.log(foo(1)); 
console.log(foo(1, 2)); 
console.log(foo(1, 2, 3)); 
console.log(foo(1, 2, 3, 4)); 
console.log(foo(1, 2, 3, 4, 5));