关于typeof
typeof
一元运算符,用来返回操作数范例的字符串。
typeof
险些不能够获得它们想要的效果。typeof
只要一个现实运用场景,就是用来检测一个对象是不是已定义或许是不是已赋值。而这个运用却不是来搜检对象的范例。
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。
对象的类定义
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 截取指定位置的字符串,以下所示:
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(2) // "[object Number]"
注:这类变化能够从 IE8 和 Firefox 4 中看出区分,以下所示:
// 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
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
援用材料: