Javascript 检查函数是否接受数组或单值输入

Javascript 检查函数是否接受数组或单值输入,javascript,Javascript,我正在尝试编写一个函数,它接受一个数组和另一个函数作为输入。关于提供的函数,我只知道它 接受单个数字参数并返回新的数字或 获取一个数字数组并返回一个新的数字数组 在我的函数中,我想检查这是第一种还是第二种情况,以确定是否使用Array.prototype.map()调用提供的函数 所以有了这两个函数 var unknownFunction = function( unknownInput ) { //Does stuff with input //returns number or a

我正在尝试编写一个函数,它接受一个数组和另一个函数作为输入。关于提供的函数,我只知道它

  • 接受单个数字参数并返回新的数字或

  • 获取一个数字数组并返回一个新的数字数组

  • 在我的函数中,我想检查这是第一种还是第二种情况,以确定是否使用
    Array.prototype.map()
    调用提供的函数

    所以有了这两个函数

    var unknownFunction = function( unknownInput ) {
      //Does stuff with input
    
      //returns number or array of numbers...
      return someValueOrValues
    }
    


    有没有办法深入第一个函数,找出调用它的最佳方法

    由于JavaScript是一种动态类型化语言,函数的输入参数一旦有人使用某个参数调用它就具有类型

    一种优雅且可行的方法是向整个给定函数添加一个属性,以提示输入参数类型:

    var func = function() {};
    func.type = "number"; // a function decorator
    
    var mainFunction = function(anArray, inputFunc) {
        if(typeof inputFunc != "function") {
             throw Error("Please supply a function as 'inputFunc'!");
        } 
    
        switch(inputFunc.type) {
            case "number":
               return anArray.map(preFunction);
    
            case "array": 
               return preFunction(anArray);
    
            default:
               throw Error("Type not supported");
        }
    };
    
    mainFunction([1,2,3], func);
    
    当您使用动态类型语言时,您需要考虑使用和/或使用进行编码。由强类型语言提供的类型安全性被良好的文档所取代

    例如:

    提供一个函数作为第二个参数,并带有一个
    类型
    属性
    main函数
    谓词的预期类型是什么 功能


    我会使用try-catch方法,但会测试实际的函数,如果其中一个函数未能尝试下一个函数

    假设这些是作为未知函数传入的函数。他们每个人只修改一个数字,将其加上1

    function onlyTakesNumber(num) {
        return num + 1;
    }
    
    function onlyTakesArray(arr) {
        return arr.map(num => num + 1);
    }
    
    现在,这是您的主要功能。在
    try
    中添加映射的原因是为了测试,确保在将数组传递给
    onlyTakesNumber
    函数时没有返回字符串。额外的测试映射将再次显示代码是否需要跳入捕获

    var mainFunction = function (anArray, preFunction) {
    
        try {
            // the map on the end checks to make sure you did not get a string back
            anArray = preFunction(anArray).map(test => test);
        }
        catch (e) {
            anArray = anArray.map(preFunction);
        }
    
        // Do whatever else with anArray
    
        return anArray;
    };
    
    
    console.log(mainFunction([1, 2, 3], onlyTakesArray)); // [2, 3, 4]
    console.log(mainFunction([7, 8, 9], onlyTakesNumber)); // [8, 9, 10]
    


    这里有一个测试,你可以在上面测试一下。最简短的回答是:“你不能”

    你可以试试看。当数组只是一个数字时,尝试访问它会导致错误…这是不可能的。通常,如果不运行函数,就无法判断函数是否接受数组或数字,即使这样,也无法确定。这是的子类,没有解决方案。@meagar是对的,但您可以使用Function.prototype.toString,在大多数浏览器中返回函数源代码+参数名的一些约定,例如,如果第一个参数名为array,则可能会返回work@meagar考虑<代码>函数未知函数(未知输入){if(Math.random()>0.5){将unknownInput视为一个数字}或者{将unknownInput视为一个数组}。此函数每次调用时都会改变其行为!这比停止问题更糟糕,因为即使对于相同的输入行为也会改变!@RaymondChen是的,我非常清楚。这不是“更糟”与停顿问题相比,这是同一个问题。我明确地说“即使那样,你也不能确定”为了解决这个问题,我们举了一个典型的例子,说明为什么停止问题很难解决。这个例子使用了您的确切逻辑,简单地用
    返回/不返回
    代替
    像对待数字一样对待
    /
    像对待数组一样对待
    。最简短的注释是“为什么?”。你不能!任何外部函数都不能访问另一个函数的参数,除非你硬编码返回它们。@ocanal,每一个昨天的JavaScript新手都知道——询问是否有某种黑客行为——是不被禁止的——但答案永远是:不,你不能——这是因为你不被允许——这是一个安全问题很高兴知道为什么我投了反对票,知道我的方法是否被打破了……马蒂亚斯,不幸的是@kevbot的观察(另一个答案)是准确的--我无法访问函数来决定是否添加类型属性。不过,我认为这是一个非常巧妙的解决方案,如果try/catch解决方案导致问题,我可能会尝试找到一种方法使此方法起作用。谢谢!@SteveLadavich正如我在评论中对另一位回答者所说的那样,您不必担心允许访问函数以向函数对象添加类型属性。只是定义这些函数的人应该添加整个属性。在AngularJS中,此模式用于定义显式注入:
    controller.$inject=[“$scope”]
    ,这是现在装饰器的常见模式。@SteveLadavich这取决于您是否采用“尝试-捕获”路线。顺便说一句,正如我所说的,这是一种反模式,是解决您的问题的最简单但最糟糕的解决方案…@SteveLadavich顺便说一句,如果您甚至无法访问函数的源代码,这不是您在问题中说过的,也不是对于那些有权访问整个源代码库的人来说,我的答案会很好用,而且因为StackOverflow答案不仅仅是给OP(你)的,所以把我的答案留给未来的访问者(或者甚至是你,如果你可以用这种方法的话)没有什么错!:)可怕的解决方案。这就是所谓的反模式@MatíasFidemraizer,您的答案甚至没有解决实际问题OP“关于提供的函数,我只知道它是……”。他无权使用函数来决定是否执行此操作:
    func.type=“number”,答案取决于此。您不需要访问该函数就可以向函数对象添加属性。正确,但他不知道要向属性添加什么值,因为他无法读取函数来知道它应该接受什么、数字或数组。顺便说一句,我的答案解决了实际问题。你的也是。您的问题是,它对性能有很大影响,而且是一种非常糟糕的编码实践。这不是“你的对我的”。。。当我在你的回答中添加评论时,我独立于我的回答:这是一个糟糕的解决方案。
    
    var mainFunction = function (anArray, preFunction) {
    
        try {
            // the map on the end checks to make sure you did not get a string back
            anArray = preFunction(anArray).map(test => test);
        }
        catch (e) {
            anArray = anArray.map(preFunction);
        }
    
        // Do whatever else with anArray
    
        return anArray;
    };
    
    
    console.log(mainFunction([1, 2, 3], onlyTakesArray)); // [2, 3, 4]
    console.log(mainFunction([7, 8, 9], onlyTakesNumber)); // [8, 9, 10]