typeof 和 instanceOf的区分

关于typeof

typeof一元运算符,用来返回操作数范例的字符串

typeof险些不能够获得它们想要的效果。typeof只要一个现实运用场景,就是用来检测一个对象是不是已定义或许是不是已赋值。而这个运用却不是来搜检对象的范例。

ValueClassType
“foo”Stringstring
new String(“foo”)Stringobject
1.2Numbernumber
new Number(1.2)Numberobject
trueBooleanboolean
new Boolean(true)Booleanobject
new Date()Dateobject
new Error()Errorobject
[1,2,3]Arrayobject
new Array(1, 2, 3)Arrayobject
new Function(“”)Functionfunction
/abc/gRegExpobject (function in Nitro/V8)
new RegExp(“meow”)RegExpobject (function in Nitro/V8)
{}Objectobject
new Object()Objectobject

上面表格中,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 操作符。

xtypeof 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

援用材料:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
  2. http://bonsaiden.github.io/JavaScript-Garden/zh/#types.instanceof
  3. https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Operators/typeof
    原文作者:PaddingMe
    原文地址: https://segmentfault.com/a/1190000000730982
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞