【问题标题】:How to not pass arguements and still make the function work?如何不传递参数并仍然使函数工作?
【发布时间】:2013-03-19 11:03:39
【问题描述】:
function drawLine(ctx, sX, sY, eX, eY, sRGB, fRGB, lWidth, capStyle)
{
    ctx.beginPath();
    ctx.moveTo(sX, sY);
    ctx.lineTo(eX, eY);
    ctx.lineWidth = lWidth||5;
    ctx.strokeStyle = 'rgb(49, 129, 48)';
    ctx.lineCap = 'round';
    ctx.stroke();
    ctx.closePath();
}

然后我想这样调用函数:

drawLine(ctx, 50, 50, 100, 100, someStrokeStyle, someFillStyle, someCapStyle);

如您所见,我跳过了lWidth 参数。我希望该函数仍然有效,即使 lWidth 没有作为参数传递。我将如何做到这一点? atm,它可能会认为someCapStylelwidth

【问题讨论】:

  • 您在参数中遗漏了一个参数,这就是我所看到的。我怎么知道那是 lWidth 参数
  • @555k 是的,当我选择不提供参数时,该函数将如何工作。
  • 您没有使用参数 fRGB 和 capStyle。所以如果你错过了一个,那么函数将被调用 capStyle=undefined。你的 lWidth 值将是 someCapStyle
  • @555k 是的,我将如何设法告诉函数我想要 lWidth 的默认值和 capStyle 的 someCapStyle 的默认值
  • 如果您希望函数使用 lWidth 作为可选参数,请将其作为函数原型中的最后一个参数

标签: javascript


【解决方案1】:

当你有大量的参数要传递给你的函数时,使用一个对象:

function foo({param1: val1, parma2: val2}) {}

在这种情况下,您将不会依赖于参数的数量和它们被表示的顺序。

所以你可以重写你的函数:

 function drawLine(drawObj)
{
    ctx.beginPath();
    ctx.moveTo(drawObj.sX, drawObj.sY);
    ctx.lineTo(drawObj.eX, drawObj.eY);
    ctx.lineWidth = drawObj.lWidth||5;
    ctx.strokeStyle = drawObj.sRGB;
    ctx.lineCap = drawObj.capStyle;
    ctx.stroke();
    ctx.closePath();
}

【讨论】:

    【解决方案2】:

    当你不传递任何参数时,undefined 值被传递,所以只需在函数中检查参数是否已传递:

    if(typeof argument == "undefined") 
    { 
       argument = "default value";
    }
    

    所以不传递lWidth,只需传递undefined 作为其值

    附:最好的方法是使用单个参数args,它将是包含所有当前参数作为属性的对象。

    【讨论】:

    • 有没有办法完全跳过它,甚至不指定 undefined?
    • @AnkurSharma 是的。使用 if(参数)
    • @555k 但是会认为定义了lWidth,没有定义capStyle。你明白我的意思吗?无论如何,没关系,我将只使用其他回答者显示的对象。感谢您的回答。
    • @AnkurSharma 你总是可以自己测试javascript如何处理参数:jsfiddle.net/BKkUE。要添加到此答案,请阅读 stackoverflow.com/questions/801032/… 上有关 undefined/null 的信息
    【解决方案3】:

    您想要的是部分评估drawLine 函数,为lWidth 分配一个常量值。有一个名为 Jeene 的 JavaScript 库就是这样做的。这就是你将如何使用它:

    function drawLine(ctx, sX, sY, eX, eY, sRGB, fRGB, lWidth, capStyle) {
        ctx.beginPath();
        ctx.moveTo(sX, sY);
        ctx.lineTo(eX, eY);
        ctx.lineWidth = lWidth || 5;
        ctx.strokeStyle = "rgb(49, 129, 48)";
        ctx.lineCap = "round";
        ctx.stroke();
        ctx.closePath();
    }
    
    Function.prototype.specialize = net.higherorder.jeene.Jeene.make();
    
    var drawLine2 = drawLine.specialize({
        lWidth: null // or whatever value you want
    });
    

    然后你使用drawLine2如下:

    drawLine2(ctx, 50, 50, 100, 100, someStrokeStyle, someFillStyle, someCapStyle);
    

    这称为专业化,是一种非常有用的模式。阅读更多信息:A Neighborhood of Infinity: The Three Projections of Doctor Futamura

    【讨论】:

    • 函数是否会自动知道 someCapStyle 是 capStyle 而不是 lWidth。
    • @AnkurSharma - 是的,确实如此。这就是专业化的真正酷之处。阅读博文以确切了解发生了什么:blog.higher-order.net/2008/09/14/jeene
    • 如果两个参数都是字符串类型怎么办?函数如何知道哪个是正确的?你能用简单的话解释一下吗?我是新手,请注意。
    • @AnkurSharma - 专业化意味着参数的名称被值替换。因此它不会混淆lWidthcapStyle。这是一种部分评估的形式。在一条评论中解释得太多了。您应该自己阅读:en.wikipedia.org/wiki/Partial_evaluation
    【解决方案4】:

    您不能在 Javascript 中使用“函数重载”,但这里有一种方法可以实现您想要的:

    How to overload functions in javascript?

    【讨论】:

      【解决方案5】:

      您可以将可选参数放在参数列表的末尾。那样的话,如果你把它去掉,其他参数就不会受到影响。

      另一种选择是传递具有您要定义的属性的单个对象,例如

      function drawLine(options) {
          options.ctx.beginPath();
          options.ctx.moveTo(options.sX, options.sY);
          options.ctx.lineTo(options.eX, options.eY);
          // etc.
       }
      

      【讨论】:

      • 这并不能真正解决问题。如果我没有在选项对象中指定 lWidth,该函数仍然会失败。我说的对吗?
      • 是的,但您可以测试它是否未定义。
      • 好的。我想可能有更简单的方法。不过没关系。谢谢你的回答。
      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 2011-05-22
      • 1970-01-01
      • 2018-06-10
      • 1970-01-01
      • 2016-08-22
      相关资源
      最近更新 更多