typeof
一元运算符,用来返回操做数类型的字符串。git
typeof
几乎不可能获得它们想要的结果。typeof
只有一个实际应用场景,就是用来检测一个对象是否已经定义或者是否已经赋值。而这个应用却不是来检查对象的类型。github
Value | Class | Type |
---|---|---|
"foo" | String | string |
new String("foo") | String | object |
1.2 | Number | number |
new Number(1.2) | Number | object |
true | Boolean | boolean |
new Boolean(true) | Boolean | object |
new Date() | Date | object |
new Error() | Error | object |
[1,2,3] | Array | object |
new Array(1, 2, 3) | Array | object |
new Function("") | Function | function |
/abc/g | RegExp | object (function in Nitro/V8) |
new RegExp("meow") | RegExp | object (function in Nitro/V8) |
{} | Object | object |
new Object() | Object | object |
上面表格中,Type 一列表示 typeof 操做符的运算结果。能够看到,这个值在大多数状况下都返回 "object"。正则表达式
Class 一列表示对象的内部属性 [[Class]] 的值。数组
JavaScript 标准文档中定义: [[Class]] 的值只多是下面字符串中的一个: Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String.
为了获取对象的 [[Class]],咱们须要使用定义在 Object.prototype 上的方法 toString。浏览器
对象的类定义ide
JavaScript 标准文档只给出了一种获取 [[Class]] 值的方法,那就是使用 Object.prototype.toString。函数
function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); return obj !== undefined && obj !== null && clas === type; } is('String', 'test'); // true is('String', new String('test')); // true
上面例子中,Object.prototype.toString 方法被调用,this 被设置为了须要获取 [[Class]] 值的对象。测试
注:Object.prototype.toString 返回一种标准格式字符串,因此上例能够经过 slice 截取指定位置的字符串,以下所示:this
Object.prototype.toString.call([]) // "[object Array]" Object.prototype.toString.call({}) // "[object Object]" Object.prototype.toString.call(2) // "[object Number]"
注:这种变化能够从 IE8 和 Firefox 4 中看出区别,以下所示:prototype
// IE8 Object.prototype.toString.call(null) // "[object Object]" Object.prototype.toString.call(undefined) // "[object Object]" // Firefox 4 Object.prototype.toString.call(null) // "[object Null]" Object.prototype.toString.call(undefined) // "[object Undefined]"
测试为定义变量
typeof foo !== 'undefined'
上面代码会检测 foo 是否已经定义;若是没有定义而直接使用会致使 ReferenceError 的异常。 这是 typeof 惟一有用的地方。
结论
为了检测一个对象的类型,强烈推荐使用 Object.prototype.toString 方法; 由于这是惟一一个可依赖的方式。正如上面表格所示,typeof 的一些返回值在标准文档中并未定义, 所以不一样的引擎实现可能不一样。
除非为了检测一个变量是否已经定义,咱们应尽可能避免使用 typeof 操做符。
x | typeof x |
---|---|
undefined | "undefined" |
true 或false | "boolean" |
任意数字或者NaN | "number" |
任意字符串 | "string" |
函数对象(在ECMA-262术语中,指的是实现了[[Call]] 的对象) | "function" |
任意内置对象(非函数) | "object" |
数组 | "obeject" |
null | "object" |
宿主对象(JS引擎内置对象,而不是DOM或者其余提供的) | 由编译器各自实现的字符串,但不是"undefined","number","boolean","number","string"。 |
正则表达式 | 各浏览器表现不一 |
若是想将null和对象区分开,则必须针对特殊值显式检测。如:my_value===null
。对于宿主对象来讲,typeof有可能并不返回‘object’,而返回字符串。但实际上客户端js中的大多数宿主对象都是‘object’类型。对于全部内置可执行对象进行typeof运算都将返回“function”。
// Numbers typeof 37 === 'number'; typeof 3.14 === 'number'; typeof Math.LN2 === 'number'; typeof Infinity === 'number'; typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字" typeof Number(1) === 'number'; // 不要这样使用! // Strings typeof "" === 'string'; typeof "bla" === 'string'; typeof (typeof 1) === 'string'; // typeof返回的确定是一个字符串 typeof String("abc") === 'string'; // 不要这样使用! // Booleans typeof true === 'boolean'; typeof false === 'boolean'; typeof Boolean(true) === 'boolean'; // 不要这样使用! // Undefined typeof undefined === 'undefined'; typeof blabla === 'undefined'; // 一个未定义的变量,或者一个定义了却未赋初值的变量 // Objects typeof {a:1} === 'object'; typeof [1, 2, 4] === 'object'; // 使用Array.isArray或者Object.prototype.toString.call方法 //能够分辨出一个数组和真实的对象 typeof new Date() === 'object'; typeof new Boolean(true) === 'object' // 使人困惑.不要这样使用 typeof new Number(1) === 'object' // 使人困惑.不要这样使用 typeof new String("abc") === 'object'; // 使人困惑.不要这样使用 // Functions typeof function(){} === 'function'; typeof Math.sin === 'function';
instanceof 左操做数是一个类,右操做数是标识对象的类。若是左侧的对象是右侧类的实例,则返回true.而js中对象的类是经过初始化它们的构造函数来定义的。即instanceof的右操做数应当是一个函数。全部的对象都是object的实例。若是左操做数不是对象,则返回false,若是右操做数不是函数,则抛出typeError。
instanceof 运算符是用来测试一个对象是否在其原型链原型构造函数的属性。其语法是object instanceof constructor
instanceof 操做符用来比较两个操做数的构造函数。只有在比较自定义的对象时才有意义。 若是用来比较内置类型,将会和 typeof 操做符 同样用处不大。
比较自定义对象
function Foo() {} function Bar() {} Bar.prototype = new Foo(); new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true // 若是仅仅设置 Bar.prototype 为函数 Foo 自己,而不是 Foo 构造函数的一个实例 Bar.prototype = Foo; new Bar() instanceof Foo; // false
instanceof 比较内置类型
new String('foo') instanceof String; // true new String('foo') instanceof Object; // true 'foo' instanceof String; // false 'foo' instanceof Object; // false
有一点须要注意,instanceof 用来比较属于不一样 JavaScript 上下文的对象(好比,浏览器中不一样的文档结构)时将会出错, 由于它们的构造函数不会是同一个对象。
结论:instanceof 操做符应该仅仅用来比较来自同一个 JavaScript 上下文的自定义对象。 正如 typeof 操做符同样,任何其它的用法都应该是避免的。
function C(){} // defining a constructor function D(){} // defining another constructor var o = new C(); o instanceof C; // true, because: Object.getPrototypeOf(o) === C.prototype o instanceof D; // false, because D.prototype is nowhere in o's prototype chain o instanceof Object; // true, because: C.prototype instanceof Object // true C.prototype = {}; var o2 = new C(); o2 instanceof C; // true o instanceof C; // false, because C.prototype is nowhere in o's prototype chain anymore D.prototype = new C(); // use inheritance var o3 = new D(); o3 instanceof D; // true o3 instanceof C; // true
var myString = new String(); var myDate = new Date(); myString instanceof String; // returns true myString instanceof Object; // returns true myString instanceof Date; // returns false myDate instanceof Date; // returns true myDate instanceof Object; // returns true myDate instanceof String; // returns false
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } var mycar = new Car("Honda", "Accord", 1998); var a = mycar instanceof Car; // returns true var b = mycar instanceof Object; // returns true
引用资料: