检查 JS 对象类型的最准确方法是什么?

typeof操作符并不能真正帮助我们找到对象的实际类型。

我已经看到了下面的代码:

Object.prototype.toString.apply(t)

问题:

这是检查对象类型的 大部分精确方法吗?

213115 次浏览
var o = ...
var proto =  Object.getPrototypeOf(o);
proto === SomeThing;

对您期望对象拥有的原型保持一个句柄,然后与它进行比较。

比如说

var o = "someString";
var proto =  Object.getPrototypeOf(o);
proto === String.prototype; // true

JavaScript 规范提供了一种正确的方法来确定对象的类:

Object.prototype.toString.call(t);

Http://bonsaiden.github.io/javascript-garden/#types

Object.prototype.toString是一种很好的方式,但它的性能是最差的。

Http://jsperf.com/check-js-type

check js type performance

使用 typeof解决一些基本问题(字符串、数字、布尔值...) ,使用 Object.prototype.toString解决一些复杂的问题(如 Array、 Date、 RegExp)。

这就是我的解决办法:

var type = (function(global) {
var cache = {};
return function(obj) {
var key;
return obj === null ? 'null' // null
: obj === global ? 'global' // window in browser or global in nodejs
: (key = typeof obj) !== 'object' ? key // basic: string, boolean, number, undefined, function
: obj.nodeType ? 'object' // DOM element
: cache[key = ({}).toString.call(obj)] // cached. date, regexp, error, object, array, math
|| (cache[key] = key.slice(8, -1).toLowerCase()); // get XXXX from [object XXXX], and cache it
};
}(this));

用作:

type(function(){}); // -> "function"
type([1, 2, 3]); // -> "array"
type(new Date()); // -> "date"
type({}); // -> "object"

接受的答案是正确的,但是我喜欢在我构建的大多数项目中定义这个小实用程序。

var types = {
'get': function(prop) {
return Object.prototype.toString.call(prop);
},
'null': '[object Null]',
'object': '[object Object]',
'array': '[object Array]',
'string': '[object String]',
'boolean': '[object Boolean]',
'number': '[object Number]',
'date': '[object Date]',
}

用法如下:

if(types.get(prop) == types.number) {


}

如果你使用的是棱形的,你甚至可以把它清楚地注射进去:

angular.constant('types', types);

我整理了一个小型的类型检查工具,灵感来自于上面的正确答案:

thetypeof = function(name) {
let obj = {};
obj.object = 'object Object'
obj.array = 'object Array'
obj.string = 'object String'
obj.boolean = 'object Boolean'
obj.number = 'object Number'
obj.type = Object.prototype.toString.call(name).slice(1, -1)
obj.name = Object.prototype.toString.call(name).slice(8, -1)
obj.is = (ofType) => {
ofType = ofType.toLowerCase();
return (obj.type === obj[ofType])? true: false
}
obj.isnt = (ofType) => {
ofType = ofType.toLowerCase();
return (obj.type !== obj[ofType])? true: false
}
obj.error = (ofType) => {
throw new TypeError(`The type of ${name} is ${obj.name}: `
+`it should be of type ${ofType}`)
}
return obj;
};

例如:

if (thetypeof(prop).isnt('String')) thetypeof(prop).error('String')
if (thetypeof(prop).is('Number')) // do something

查找对象的 REAL 类型的最佳方法(包括本机对象或 DataType 名称(如 String、 Date、 Number、。.和对象的真实类型(甚至是自定义类型) ; 是通过获取对象原型的构造函数的 name 属性:

原生型 Ex1:

var string1 = "Test";
console.log(string1.__proto__.constructor.name);

展示:

String

练习2:

var array1 = [];
console.log(array1.__proto__.constructor.name);

展示:

Array

自订课程:

function CustomClass(){
console.log("Custom Class Object Created!");
}
var custom1 = new CustomClass();


console.log(custom1.__proto__.constructor.name);

展示:

CustomClass

我认为,这里展示的大多数解决方案都存在过度设计的问题。检查一个值是否为 [object Object]类型的最简单方法可能是检查它的 .constructor属性:

function isObject (a) { return a != null && a.constructor === Object; }

甚至更短的箭头函数:

const isObject = a => a != null && a.constructor === Object;

a != null部分是必需的,因为可以传入 nullundefined,而且不能从其中任何一个中提取构造函数属性。

它适用于通过以下方式创建的任何对象:

  • Object构造函数
  • 字面意思 {}

它的另一个优秀特性是,它能够为使用 Symbol.toStringTag的自定义类提供正确的报告。例如:

class MimicObject {
get [Symbol.toStringTag]() {
return 'Object';
}
}

这里的问题是,当对它的一个实例调用 Object.prototype.toString时,将返回错误的报告 [object Object]:

let fakeObj = new MimicObject();
Object.prototype.toString.call(fakeObj); // -> [object Object]

但是对构造函数进行检查会得到一个正确的结果:

let fakeObj = new MimicObject();
fakeObj.constructor === Object; // -> false

我知道的一个老问题。你不需要转换它。看看这个函数:

function getType( oObj )
{
if( typeof oObj === "object" )
{
return ( oObj === null )?'Null':
// Check if it is an alien object, for example created as {world:'hello'}
( typeof oObj.constructor !== "function" )?'Object':
// else return object name (string)
oObj.constructor.name;
}


// Test simple types (not constructed types)
return ( typeof oObj === "boolean")?'Boolean':
( typeof oObj === "number")?'Number':
( typeof oObj === "string")?'String':
( typeof oObj === "function")?'Function':false;


};

例子:

function MyObject() {}; // Just for example


console.log( getType( new String( "hello ") )); // String
console.log( getType( new Function() );         // Function
console.log( getType( {} ));                    // Object
console.log( getType( [] ));                    // Array
console.log( getType( new MyObject() ));        // MyObject


var bTest = false,
uAny,  // Is undefined
fTest  function() {};


// Non constructed standard types
console.log( getType( bTest ));                 // Boolean
console.log( getType( 1.00 ));                  // Number
console.log( getType( 2000 ));                  // Number
console.log( getType( 'hello' ));               // String
console.log( getType( "hello" ));               // String
console.log( getType( fTest ));                 // Function
console.log( getType( uAny ));                  // false, cannot produce
// a string

低成本,简单易行。

最佳解决方案toString(如上所述) :

function getRealObjectType(obj: {}): string {
return Object.prototype.toString.call(obj).match(/\[\w+ (\w+)\]/)[1].toLowerCase();
}

enter image description here

公平警告: toString认为 NaNnumber,所以你必须在以后用 Number.isNaN(value)手动保护。

另一种解决方案是使用 Object.getPrototypeOf 失败nullundefined

Using constructor