9

在 Javascript 中,有没有办法检查函数参数的类型?我想编写一个名为的函数checkTypes,它执行以下操作:

function checkTypes(typeArr){
    //if the types do not match typeArr, throw an error
}

function exampleUsage(arr1, arr2, num1){
    checkTypes("object", "object", "number");
    //throw an error if the types do not match the corresponding elements
}
4

7 回答 7

14

您可以使用typeOf改编自这篇文章Fixing the JavaScript typeof operator的函数与此函数相结合:

function typeOf( obj ) {
  return ({}).toString.call( obj ).match(/\s(\w+)/)[1].toLowerCase();
}

function checkTypes( args, types ) {
  args = [].slice.call( args );
  for ( var i = 0; i < types.length; ++i ) {
    if ( typeOf( args[i] ) != types[i] ) {
      throw new TypeError( 'param '+ i +' must be of type '+ types[i] );
    }
  }
}

function foo( a,b,c ) {
  checkTypes( arguments, ['string', 'number', 'array'] );
  return 'foo';
}

console.log( foo( 'a', 1, [2] ) ); //=> foo
console.log( foo( 1, 1, [2] ) ); 
//^ Uncaught TypeError: param 0 must be of type string
于 2012-12-18T04:33:30.720 回答
10

typeof在这种情况下不要使用。有几个原因是有问题的:

typeof null                 // 'object'
typeof []                   // 'object'
typeof 'foo'                // 'string'
typeof new String('foo')    // 'object'
'foo' == new String('foo')  // true

相反,使用Object::toString

Object.prototype.toString.call(null)               // '[object Null]'
Object.prototype.toString.call([])                 // '[object Array]'
Object.prototype.toString.call('foo')              // '[object String]'
Object.prototype.toString.call(new String('foo'))  // '[object String]'

装饰师将满足您的要求:

var getType = function(value) {
  return Object.prototype.toString.call(value)
    .replace(/^\[object |\]$/g, '').toLowerCase();
};

var checkTypes = function(types, fn) {
  return function() {
    var args = Array.prototype.slice.call(arguments, 0);
    for (var idx = 0; idx < types.length; idx += 1) {
      var expected = types[idx];
      var received = getType(args[idx]);
      if (received != expected) {
        throw new TypeError('expected ' + expected + '; received ' + received);
      }
    }
    fn.apply(null, args);
  };
};

var exampleUsage = checkTypes(['array', 'array', 'number'], function(arr1, arr2, num1) {
  console.log('arr1:', arr1);
  console.log('arr2:', arr2);
  console.log('num1:', num1);
});

使用示例:

exampleUsage([], [], 0);
// arr1: []
// arr2: []
// num1: 0

exampleUsage([], [], 'foo');
// TypeError: expected number; received string
于 2012-12-18T06:27:21.163 回答
3

您可以使用伪数组的修改版本typeofarguments获取每个参数类型并将其与所需的类型集进行比较:

// from Doug Crockford http://javascript.crockford.com/remedial.html
function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (Object.prototype.toString.call(value) == '[object Array]') {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

function checkTypes(argList, typeList) {
    for (var i = 0; i < typeList.length; i++) {
        if (typeOf(argList[i]) !== typeList[i]) {
            throw 'wrong type: expecting ' + typeList[i] + ", found " + typeOf(argList[i]);
        }
    }
}

工作演示:http: //jsfiddle.net/jfriend00/ywyLe/


示例用法:

function exampleUsage(arr1, arr2, num1){
    //throw an error if the types do not match the corresponding elements
    checkTypes(arguments, ["array", "array", "number"]);
}
于 2012-12-18T04:44:07.857 回答
0

您正在寻找typeof运算符。

于 2012-12-18T04:24:50.413 回答
0

大多数事情的typeof函数返回对象,

alert(typeof("this is string")); /* string */
alert(typeof(1234)); /* number */
alert(typeof([])); /* object */
alert(typeof({})); /* object */
alert(typeof(new Date)); /* object */
alert(typeof(function(){})); /* function */

但是 jQuery 可以通过这个函数识别 jQuery.type( obj ) http://api.jquery.com/jQuery.type/

于 2012-12-18T04:47:18.950 回答
0

如果有人正在寻找类似需求的环境解决方案,我可以推荐typeof-arguments包。

const checkTypes = require('typeof-arguments');

function exampleUsage(arr1, arr2, num1){
  checkTypes(arguments,["object", "object", "number"]);
  //throw an error if the types do not match the corresponding elements
}
于 2017-07-26T03:38:47.927 回答
-4

JavaScript 不适合类型。此外,您不能从调用函数神奇地访问父函数的参数。

如果您不想头疼,请使用一些简单的库来检查类型。

例如,使用underscore.js ,您可以编写如下内容:

function exampleUsage(arr1, arr2, num1) {
  if(!_.isArray(arr1) || !_.isArray(arr2) || !_.isNumber(num1) {
    throw "Wrong types"
  }
  // do other stuff
}

您可能害怕类型,因为您可能是动态语言的新手。你会发现这并不像看起来那么糟糕,但是 JavaScrip 很糟糕(出于许多其他原因)

于 2012-12-18T04:31:51.607 回答