浅谈 Object.prototype.toString.call()

浅谈 Object.prototype.toString.call()

今天学习 vue 看 node_modules 源码,看到 shallow-clone、以及 clone-deep 时,isPlainObject() 方法源码中使用 Object.prototype.toString.call(o) === ‘[object Object]’ 判断 o 是否是对象。所以后面将自己的理解与总结记录下来。

广为人知判断 js 数据类型的方法

js基本类型:null undefined string number boolean symbol(ES6新增)

js内置引用类型:Object Array Function Date RegExp Error …

typeof 操作符判断基本类型

console.log(typeof 'a') // string
console.log(typeof 1) // number
console.log(typeof true) // boolean
console.log(typeof undefined) // undefined
console.log(typeof symbol('1')) // symbol
// typeof null 是 object, js 遗留的 bug
console.log(typeof null) // object

// 大多引用型对象返回 object
console.log(typeof {}) // object
console.log(typeof []) // object
// 例外
console.log(typeof function a() {}) // function

instanceof 操作符判断引用类型

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

// 对象
console.log({} instanceof Object) // true
// 数组
console.log([] instanceof Array) // true
// 日期对象
console.log(new Date() instanceof Date) // true
// 函数
console.log(function a() {} instanceof Function) // true
// 正则
console.log(/a+/ instanceof RegExp) // true

// 所有引用类型对象的 __proto__ 都指向 Object.prototype
console.log([] instanceof Object) // true
console.log(function a() {} instanceof Object) // true
...

Object.prototype.toString.call/apply() 判断任何数据类型

不存在浏览器兼容性问题

判断基本类型

console.log(Object.prototype.toString.call('a')) // [object String]
console.log(Object.prototype.toString.call(1)) // [object Number]
console.log(Object.prototype.toString.call(false)) // [object Boolean]
console.log(Object.prototype.toString.call(undefined)) // [object Undefined]
console.log(Object.prototype.toString.call(null)) // [object Null]
console.log(Object.prototype.toString.call(Symbol(1))) // [object Symbol]

判断引用类型

console.log(Object.prototype.toString.call({})) // [object Object]
console.log(Object.prototype.toString.call([])) // [object Array]
console.log(Object.prototype.toString.call(new Date())) // [object Date]
console.log(Object.prototype.toString.call(function a(){})) // [object Function]
console.log(Object.prototype.toString.call(/a+/)) // [object RegExp]

Object.prototype.toString.call/apply() 原理

首先,说一下 Object 和 Object.prototype

Object 是创建 js 对象的构造函数,我们可以用 new 操作符创建一个对象

var person = new Object({name: 'Tom'}); // {name: 'Tom'}
// 等同于
var person = {name: 'Tom'}; // {name: 'Tom'}

接下来看一下另一种创建 person 对象的方法

// 声明一个 Person 构造函数
function Person(name) {
	this.name = name;
	// 我们重写一下 toString() 方法
	this.toString = function() {
		console.log('Name:', this.name);
	}
}
var person = new Person('Tom'); // {name: 'Tom'}
person.toString(); // Name: Tom

Object.prototype.toString.call(person) 输出 [object Object],说明 Object.prototype.toString.call(person) 不会调用 Person 的 toString()方法

Object.prototype.toString.call(person); // [object Object]

Object.prototype 属性表示 Object 的原型对象,在 javascript 中几乎所有的对象都是 Object 的实例
控制台打印一下 Object.prototype,我们可以看到是一个对象,有很多内置的方法,我们现在只讨论 toString() 方法

constructor : ƒ Object()
hasOwnProperty : ƒ hasOwnProperty()
...
toString : ƒ toString()
...

接下来,说一下 toString() 方法

在js中,每个对象都有 toString() 方法,返回对象的字符串形式,但是不同对象 toString() 的结果又有差异,这是因为 js 不同构造函数实现 toString() 的方法不同

console.log('a'.toString()); // "a"
console.log(Symbol(1).toString()) // "Symbol(1)"
// 按照字符串的 toString() 方法,结果应该是 "[1,2,3]",事实却不是,所以证明两个方法实现不同
console.log([1,2,3].toString()) // "1,2,3"
// Object 构造函数实现的 toString() 方法
console.log({a:1}.toString()) // "[object Object]"

现在模拟一下 Object 构造函数实现 toString() 方法

function MyObject(o) {
	this.toString = function() {
		// 此处只是模拟生成 [object Object] 的格式
		return `[object ${o.constructor.name}]`;
	}
}
var person = new MyObject({name: 'Tom'});
person.toString(); // "[object Object]"
var arr = new MyObject([1,2,3]);
person.toString(); // "[object Array]"

结论

Object.prototype.toString.call/apply() 其实是利用 Object.prototype.toString() 方法可以返回 “[obejct 对象构造函数名]” 的原理来确定数据类型,并且 js 中所有对象都是Object 的实例,可以使用 call/apply 调用 Object.prototype 原型对象的 toString() 方法。

至于 Object.prototype.toString() 内部实现原理,等到有机会再去研究。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值