为什么Object.prototype.toString.call( )能够准确判断值类型?

186 阅读2分钟
前提知识:

1.typeof 用来判断基础类型值和function

2.instanceof 用来判断对象的不同子类型的值类型,比如数组、函数、对象

3.Object.prototype.toString.call( )可以判断所有类型

js中的内置函数对象

Date、Array、String、Regexp、Boolean、Function、Object、Number

这些都是js内置的函数对象,这些对象上都有系统自带的一些常用方法,可以用new标识符创建对象实例。

var arr = new String('1111');

typeof arr; // Object

arr instanceof String; // true

var arr2 = '2222';

typeof arr2; // String

arr instanceof String; // false

这里要重点写一下instanceof这个特性

用法:实例 instanceof 构造函数

只要是构造函数prototype属性指向的原型对象,在实例的原型链上就返回true。

由于arr2只是一个基础值类型,并不是对象实例,所以也就没有什么原型对象,只能返回false

既然arr2是基本类型,为什么可以调用arr.toString()方法?

通过内置函数创建的对象是包装了基本类型的对象。

var arr = new String('1111');

以该代码为例:

原型链的关系是:arr.__proto__ === String.prototype

String函数对象又是Object的实例

String.__proto__ === Object.prototype

因此,arr作为包装了基本类型的对象,可以通过原型链找到Object.prototype上的toString方法。

var arr2 = '2222';

arr2作为一个基本类型值,在调用toString()方法时,js引擎会把它自动转换成一个封装对象,也就是String对象实例。

所有内置对象创建的实例都有[[class]]属性

这个属性跟内置对象的类型相对应,这个属性看不到也不能访问,只能通过Object.prototype.toString().call()来访问.

Object.prototype.toString.call('111')
'[object String]'

Object.prototype.toString.call(function fn(){})
'[object Function]'
问题1:为什么基本类型值也能输出正确类型呢?

js引擎会将基本类型值自动包装成内置对象的实例。

问题2:我为什么不能通过arr.toString()来调用

这里其实涉及到继承,Object对象其实是继承链的顶级,其他内置对象都是Object函数对象的实例。
发生继承关系时,子对象可以使用父对象的方法,但是子对象也可以改写父对象中的方法。

toString对象就是子对象改写父对象方法的例子。

只有调用Object原型对象上的toString方法才可以输出`[[class]]`属性