Javascript 使用Object.prototype.toString()对内置类型进行常规类型检查

Javascript 使用Object.prototype.toString()对内置类型进行常规类型检查,javascript,typechecking,Javascript,Typechecking,我想知道使用Object.prototype.toString()对内置类型进行常规类型检查是否合适。我有一个函数如下所示: // Return the built-in type of an object. var typeOf = (function() { var reType = /\[object (\w+)\]/; return function typeOf(obj) { return reType.exec(Object.prototype.toString.c

我想知道使用Object.prototype.toString()对内置类型进行常规类型检查是否合适。我有一个函数如下所示:

// Return the built-in type of an object.
var typeOf = (function() {
  var reType = /\[object (\w+)\]/; 
  return function typeOf(obj) {
    return reType.exec(Object.prototype.toString.call(obj))[1];
  };
})();
对函数的调用将返回以下结果:

console.log( typeOf(null) );         // => Null
console.log( typeOf(undefined) );    // => Undefined
console.log( typeOf([]) );           // => Array
console.log( typeOf(true) );         // => Boolean
console.log( typeOf(new Date()) );   // => Date
console.log( typeOf(new Error()) );  // => Error
console.log( typeOf(function(){}) ); // => Function 
console.log( typeOf(1) );            // => Number
console.log( typeOf({}) );           // => Object
console.log( typeOf(/ /) );          // => RegExp
console.log( typeOf("") );           // => String
除了它可能比其他形式的类型检查慢之外,这是可以接受的吗

我问这个问题的原因之一是因为我想为我正在处理的项目编码和序列化对象的内置类型。我正在考虑将返回的类型传递给返回数字代码的函数:

// Encode a built-in type as a number.
var encodeType = (function() {
  var types = {
    'Null':      0,
    'Undefined': 1,
    'Array':     2,
    'Boolean':   3,
    'Date':      4,
    'Error':     5,
    'Function':  6,
    'Number':    7,
    'Object':    8,
    'RegExp':    9,
    'String':    10,
    'Arguments': 11,
    'Math':      12,
    'JSON':      13
  };
  return function encodeType(type) {
    return types[type];
  }
})();
因此,输出变为:

console.log(encodeType( typeOf(null) ));         // => 0
console.log(encodeType( typeOf(undefined) ));    // => 1
console.log(encodeType( typeOf([]) ));           // => 2
console.log(encodeType( typeOf(true) ));         // => 3
console.log(encodeType( typeOf(new Date()) ));   // => 4
console.log(encodeType( typeOf(new Error()) ));  // => 5
console.log(encodeType( typeOf(function(){}) )); // => 6
console.log(encodeType( typeOf(1) ));            // => 7
console.log(encodeType( typeOf({}) ));           // => 8
console.log(encodeType( typeOf(/ /) ));          // => 9
console.log(encodeType( typeOf("") ));           // => 10
用这种方式进行类型检查有什么缺陷吗?感谢您的见解。

以下是实施:

  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
    _['is' + name] = function(obj) {
      return toString.call(obj) === '[object ' + name + ']';
    };
  });
所以,是的,这种方法很好用


p.S.
toString
是上述代码中
Object.prototype.toString
的缩写。

我不理解所有额外的语法。这不会做完全相同的事情吗

var typeOf = function(obj) {
    var reType = /\[object (\w+)\]/;
    return reType.exec(Object.prototype.toString.call(obj))[1];
    };

此外,最好使用encodeType

的开关,使其看起来不错。如果您实际上不需要在程序中使用类型信息,另一种选择是使用类型强制编译器,例如闭包编译器支持类型注释。我开始摆弄
eval(“obj instanceof”+types[I])
,看看这是否为您提供了一种更安全的方法,但它只会返回
Object
,用于一些类似数字和布尔值的对象-事实上,这一页的功能与您的建议相同:这里是否有潜在的问题?是的,人们总是使用
Object.prototype.toString
进行类型检查。是的,它是可以接受的,不,它并不比其他类型的类型检查慢,而且不,这里没有我能想到的陷阱。唯一的区别是闭包建议只编译正则表达式一次,而不是每次调用函数时(请参见这里的第二个答案:)。它可能会或可能不会产生具体的区别,我没有计时。我指的是额外的返回函数和围绕您的函数类型的额外附件,我在上面的示例中删除了这些函数。我倾向于尽可能避免Javascript中的switch语句。这是我个人的偏好——我认为object-literal符号更清晰,更容易阅读。我不知道它是否比switch语句快。更干净更容易阅读是的,但你没有考虑意外输入,每次调用函数时都会重新创建变量。好的,我明白你的意思。你提到的链接让我觉得你指的是完全不同的东西。我知道您基本上是在创建一个私有持久变量来保存函数的正则表达式。对口译员来说,这可能会更复杂。我想这取决于解释器的内置优化。谢谢你的解释。我为Chrome制作了一个密码管理器扩展,我使用了类似的方法来保护加密密钥不被JavaScript控制台窥探。