欢迎光临散文网 会员登陆 & 注册

typeof 和 instanceof

2021-05-30 02:37 作者:刂C刂C刂  | 我要投稿

typeof :

typeof 运算符,用于检测数据类型。返回值为对应数据类型的字符串

语法:typeof operand 或 typeof(operand)


typeof 123  // number

typeof true  // boolean

typeof '123'  // string

typeof undefined  // undefined


typeof null  // object 


typeof [ ]  // object

typeof new Date()  // objec

typeof { }  // object


typeof function() { }  // function

typeof Array  // function

 

typeof Symbol()   // Symbol

  1. 为什么 typeof null 返回 object ?

    js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息。而 typeof 关键字检测数据类型的原理就是通过检测这1-3位机器码实现检测不同数据类型。 比如 object类型的数据,对应的机器码就是:000

      000:对象         1:整数          010:浮点数          100:字符串         110:布尔值

      undefined: -2^30          null:全零

  2. null 类型的数据存储时,对应的机器码是一串的 000000......000000

    所以typeof在检测 null 类型的数据,会返回 object。这个JavaScript这门语言的一个 特点。

  3. typeof 检测引用类型数据结构,都返回应该object,但是为什么还会返回 function ?

    因为:typeof 在检测出其为引用数据类型后,还会再检测这个引用数据类型是否有实现[[call]]方法不是 则返回object , 则返回function。

  4. 极易混淆的一个点:

var str1 = 'myStr';

var str2 = new String( 'myStr' );

typeof str1;  // string

typeof str2;  // object

这里记住一点就行:当我们 new 一个构造函数时, 结果肯定是实例化了一个对象。所以其肯定是引用数据类型。接着我们只需要判断这个引用数据类型是否实现[[call]]方法不是 则返回object , 则返回function。



instanceof:

语法: 实例对象 instanceof  类    属于返回 true ,不属于返回 false。

原理是:检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。返回值为布尔值。

利用这一点,instanceof  也可以用于检测数据类型。

缺点1:检测的实例必须是对象数据类型,基本数据类型(Number String Boolean null undefined Symbol)无法通过 instanceof 检测的。

缺点2:只要构造函数在这个被检测的实例的原型链上存在,就都返回 true。 所以即使是检测对象数据类型, instanceof 也是不准确的。

let reg = /^$/;

let str1 = new String(123);

let str2 = 'abc';

let num = 100;

console.log(reg instanceof RegExp);   // true   字面量创建的正则也还是对象
console.log(str1 instanceof String);    // true 
console.log(str2  instanceof String);   // false   字面量创建出的基本数据类型无法检测
console.log(num instanceof Number);   // false


console.log([] instanceof Array);   // true

console.log( [] instanceof Object);  // true

 



检测引用类型更好的方法是使用: Object.prototype.toString() 我们先讨论 toString() 这个方法,对象的 toString() 方法,如果在自定义对象中未被覆盖toString() 返回 "[object type]"。这里的 type 指 对应的类型。

但是 Boolean、String、Number、Function、Array、Date、RegExp的原型对象上也 都定义了各自的 toString() 方法。它们会覆盖Object原型上的 toString()。

console.log({}.toString()); // '[object Object]'

// 会被覆盖的原因在于:原型链查找的就近原则

// 1. 'abc' 是个原始值,是基本数据类型。

// 2. 我们要对他使用方法,就会发生 包装类 。

// 3. 而包装类时,是通过 new String 这个构造函数创建实例的。

// 4. 当我们调用 toString() 这个方法时,这个新生成的实例上并没有这个方法,所以会去它的原型上寻找。

// 5. 而我们前面说过,String.prototype 是有自己预定义的 toSting() 方法的。

console.log(('abc').toString()); // 'abc'

console.log((100).toString()); // '100'

console.log(true.toString()); // 'true'

console.log([1,2,3].toString());  // '1,2,3'

console.log(function(){}.toString()); // 'function(){}'

console.log(new Date().toString());  // 当前时间

console.log(/1231/g.toString());  // '/1231/g'


所以我们可以通过直接使用 Object.prototype.toString() 来判断类型,这个方法执行时会把内部 this 的所属类信息输出。

Object.prototype.toString() 方法执行的时候,方法中的 this 是谁,就会检测谁的类型。所以需要使用 Function.prototype.call() 来改变Object.prototype.toString()this,使之变为我们要检测的数据。

console.log(Object.prototype.toString.call(/123/));   //  [object RegExp]

console.log(Object.prototype.toString.call(123));  //  [object Number]

console.log(Object.prototype.toString.call('abc'));   //  [object String]

console.log(Object.prototype.toString.call([1,2,3]));  //  [object Array]


其实也可以像下面简写,反正只要指向的Object原型对象上的 toString() 就行。

console.log({}.toString.call( new Data() ) );   //  [object Date]


扩展:Symbol.toStringTag

在调用 Object.prototype.toString() 方法时,会去读取这个标签并把它包含在自己的返回值里。

内置的 JavaScript 对象类型能识别并返回特定的类型标签,是因为引擎为它们设置好了对应的 Symbol.toStringTag 标签。

MDN



typeof 和 instanceof的评论 (共 条)

分享到微博请遵守国家法律