Vue源码中要const _toStr = Object.prototype.toString的原因分析

所属分类: 网络编程 / JavaScript 阅读数: 1565
收藏 0 赞 0 分享

在vue的源码中,vue/src/shared/util.js文件中存放的是一些方法。其中作者用了Object.prototype.toString这个方法来判断类型,但是并没有直接用,而是单独保存在一个变量:

const _toStr = Object.prototype.toString

那么为什么要这么做呢?

先说下判断类型。众所周知,typeof在判断对象时不能正确判断Null,并且不能识别出Array,但在判断基础类型时是没问题的。所以尤大也写了:

export function isPrimitive (value: any): boolean %checks {
 return (
 typeof value === 'string' ||
 typeof value === 'number' ||
 // $flow-disable-line
 typeof value === 'symbol' ||
 typeof value === 'boolean'
 )
}

判断Object也做了区分,isObject和isPlainObject :

export function isObject (obj: mixed): boolean %checks {
 return obj !== null && typeof obj === 'object'
}
export function isPlainObject (obj: any): boolean {
 return _toString.call(obj) === '[object Object]'
}

到了判断复杂类型的时候,一般我们用Object.prototype.toString或者是instanceof。如果是前者的话会返回类似'[object Object]'的字符串。后者则会判断一个对象的原型链上是否存在一个构造函数。

两者还有一些不同。Object.prototype.toString.call(1) Object.prototype.toString.call(Number(1))时,返回的都是"[object Number]",也就是说,它并不能区分原始类型和复杂类型。可见,Object.prototype.toString.call并不像很多教程说的那样好用。

Object.prototype.toString.call(1)
"[object Number]"
Object.prototype.toString.call(Number(1))
"[object Number]"

如果要使用,就需要像尤大一样,把原始类型单独拎出来判断,再去判断复杂类型,而走到这一步的时候尤大就写了上面说那行const _toStr。这是因为,toString实在是太容易被重写了。如果toString被其他人重写,将会对代码中涉及到的部分造成影响,所以就保存下来防止这种情况发生。

补充:Object.prototype.toString方法的原理

前言

我们在判断一个对象的内置类型时,我们一般可以使用以下方法:

var arr = [];
console.log(Object.prototype.toString.call(arr)) //"[object Array]"

那么,这个方法的原理是什么呢?

ECMAScript 3

在toString方法被调用时,会执行下面的操作步骤:

1. 获取this对象的[[Class]]属性的值.

2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串.

3. 返回第二步的操作结果Result(2).

[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性.在规范中,[[Class]]是这么定义的

[[Class]] 一个字符串值,表明了该对象的类型.

然后给了一段解释:

所有内置对象的[[Class]]属性的值是由本规范定义的.所有宿主对象的[[Class]]属性的值可以是任意值,甚至可以是内置对象使用过的[[Class]]属性的值.[[Class]]属性的值可以用来判断一个原生对象属于哪种内置类型.需要注意的是,除了通过Object.prototype.toString方法之外,本规范没有提供任何其他方式来让程序访问该属性的值。

ECMAScript 5

在toString方法被调用时,会执行下面的操作步骤

如果this的值为undefined,则返回"[object Undefined]".
如果this的值为null,则返回"[object Null]".
让O成为调用ToObject(this)的结果.
让class成为O的内部属性[[Class]]的值.
返回三个字符串"[object ", class, 以及 "]"连接后的新字符串.
ES5中,[[Class]]属性的解释更加详细:

所有内置对象的[[Class]]属性的值是由本规范定义的.所有宿主对象的[[Class]]属性的值可以是除了"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String"之外的的任何字符串.[[Class]]内部属性是引擎内部用来判断一个对象属于哪种类型的值的.需要注意的是,除了通过Object.prototype.toString方法之外,本规范没有提供任何其他方式来让程序访问该属性的值。

总而言之,要获取一个对象的真实的内置类型,我们需要通过获取[[Class]]的属性值,在es5之前,该属性值只能通由Object.prototype.toString来访问,因此,通过Object.prototype.toString.call(arr)改变tostring方法的this指向,从而获得对象的内置类型。

以上所述是小编给大家介绍的Vue源码中要const _toStr = Object.prototype.toString的原因分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多精彩内容其他人还在看

AngularJs IE Compatibility 兼容老版本IE

本文主要介绍AngularJs IE Compatibility 兼容老版本IE的问题及解决办法,有兴趣的小伙伴可以参考下
收藏 0 赞 0 分享

AngularJs Modules详解及示例代码

本文主要介绍AngularJs Modules的相关知识,这里整理了详细的资料及简单示例代码,有兴趣的朋友可以参考下
收藏 0 赞 0 分享

AngularJs Scope详解及示例代码

本文主要介绍AngularJs Scope的知识,这里整理了详细资料及示例代码,有兴趣的小伙伴可以参考下
收藏 0 赞 0 分享

node.js中module.exports与exports用法上的区别

Node.js 引入了模块(Module)概念,一个模块可以通过module.exports 或 exports 将函数、变量等导出,以使其它 JavaScript 脚本通过require() 函数引入并使用。那么node.js中module.exports与exports有什么
收藏 0 赞 0 分享

基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)

这篇文章主要介绍了基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

基于jQuery实现发送短信验证码后的倒计时功能(无视页面关闭)

最近做了一个项目,其中有需求要求实现发送短信验证码后倒计时功能,其中有个难点:要求关闭页面也进行倒计时。好吧,下面小编把jquery 发送验证码倒计时的实现代码分享给大家,大家可以参考下
收藏 0 赞 0 分享

js绘制购物车抛物线动画

这篇文章主要为大家详细介绍了js绘制购物车抛物线动画,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

vue.js入门教程之绑定class和style样式

小编之前介绍了通过vue.js计算属性,不知道大家都学会了吗。那这篇文章中我们将一起学习vue.js实现绑定class和style样式,有需要的朋友们可以参考借鉴。
收藏 0 赞 0 分享

纯JS实现可拖拽表单的简单实例

下面小编就为大家带来一篇纯JS实现可拖拽表单的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

js实现StringBuffer的简单实例

下面小编就为大家带来一篇js实现StringBuffer的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多