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


Posted in Javascript onDecember 09, 2018

在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的原因分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Highslide.js是一款基于js实现的网页中图片展示插件
Mar 30 Javascript
JavaScript Distilled 基础知识与函数
Apr 07 Javascript
javascript URL编码和解码使用说明
Apr 12 Javascript
js防止表单重复提交实现代码
Sep 05 Javascript
Ajax执行顺序流程及回调问题分析
Dec 10 Javascript
js拖动div 当鼠标移动时整个div也相应的移动
Nov 21 Javascript
jquery任意位置浮动固定层插件用法实例
May 29 Javascript
js删除数组元素、清空数组的简单方法(必看)
Jul 27 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
Aug 20 Javascript
微信小程序中上传图片并进行压缩的实现代码
Aug 28 Javascript
node.js的Express服务器基本使用教程
Jan 09 Javascript
微信小程序自定义弹窗滚动与页面滚动冲突的解决方法
Jul 16 Javascript
vue form check 表单验证的实现代码
Dec 09 #Javascript
关于Vue Router中路由守卫的应用及在全局导航守卫中检查元字段的方法
Dec 09 #Javascript
vue打包之后生成一个配置文件修改接口的方法
Dec 09 #Javascript
基于Vue-Cli 打包自动生成/抽离相关配置文件的实现方法
Dec 09 #Javascript
JS数组去重的6种方法完整实例
Dec 08 #Javascript
原生JS实现的放大镜特效示例【测试可用】
Dec 08 #Javascript
JS实现的小火箭发射动画效果示例
Dec 08 #Javascript
You might like
成本8450万,票房仅2亿,口碑两极分化,又一部DC电影扑街了
2020/04/09 欧美动漫
ThinkPHP3.2框架操作Redis的方法分析
2019/05/05 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
jQuery 通过事件委派一次绑定多种事件,以减少事件冗余
2010/06/30 Javascript
解决JQeury显示内容没有边距内容紧挨着浏览器边线
2013/12/20 Javascript
jQuery中removeAttr()方法用法实例
2015/01/05 Javascript
javascript实现获取浏览器版本、操作系统类型
2015/01/29 Javascript
了解Javascript的模块化开发
2015/03/02 Javascript
jQuery给元素添加样式的方法详解
2015/12/30 Javascript
基于Javascript实现二级联动菜单效果
2016/03/04 Javascript
jQuery Easyui 验证两次密码输入是否相等
2016/05/13 Javascript
JS实现简单的右下角弹出提示窗口完整实例
2016/06/21 Javascript
vue获取input输入值的问题解决办法
2017/10/17 Javascript
原生nodejs使用websocket代码分享
2018/04/07 NodeJs
微信小程序中使用ECharts 异步加载数据的方法
2018/06/27 Javascript
js实现列表按字母排序
2020/08/11 Javascript
通过实例解析jQ Ajax操作相关原理
2020/09/23 Javascript
Python实现串口通信(pyserial)过程解析
2019/09/25 Python
python使用itchat模块给心爱的人每天发天气预报
2019/11/25 Python
使用python-opencv读取视频,计算视频总帧数及FPS的实现
2019/12/10 Python
python matplotlib.pyplot.plot()参数用法
2020/04/14 Python
vscode+PyQt5安装详解步骤
2020/08/12 Python
Anaconda+spyder+pycharm的pytorch配置详解(GPU)
2020/10/18 Python
CSS3 calc()会计算属性详解
2018/02/27 HTML / CSS
魔声耳机官方网站:Monster是世界第一品牌的高性能耳机
2016/10/26 全球购物
Java面试笔试题大全
2016/11/23 面试题
关于是否需要写商业计划书
2014/02/07 职场文书
高中生家长寄语大全
2014/04/03 职场文书
我有一个梦想演讲稿
2014/05/05 职场文书
三关爱志愿服务活动方案
2014/08/17 职场文书
检讨书范文
2015/01/27 职场文书
2015年工会工作总结
2015/03/30 职场文书
2015年防汛工作总结
2015/05/15 职场文书
《学会生存》读后感3篇
2019/12/09 职场文书
解决Tkinter中button按钮未按却主动执行command函数的问题
2021/05/23 Python
OpenFeign实现远程调用
2022/08/14 Java/Android