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 相关文章推荐
js格式化货币数据实现代码
Sep 04 Javascript
JQuery伸缩导航练习示例
Nov 13 Javascript
Extjs4.0 ComboBox如何实现三级联动
May 11 Javascript
原生Javascript和jQuery做轮播图简单例子
Oct 11 Javascript
用Vue-cli搭建的项目中引入css报错的原因分析
Jul 20 Javascript
详解Js中的模块化是如何实现的
Oct 18 Javascript
在vue项目中引入highcharts图表的方法
Jan 21 Javascript
el-select数据过多懒加载的解决(loadmore)
May 29 Javascript
vue在路由中验证token是否存在的简单实现
Nov 11 Javascript
vue vant Area组件使用详解
Dec 09 Javascript
Vue element-ui父组件控制子组件的表单校验操作
Jul 17 Javascript
vue element el-transfer增加拖拽功能
Jan 15 Vue.js
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
Windows中安装Apache2和PHP4权威指南
2006/11/18 PHP
一个PHP操作Access类(PHP+ODBC+Access)
2007/01/02 PHP
php 用sock技术发送邮件的函数
2007/07/21 PHP
鸡肋的PHP单例模式应用详解
2013/06/03 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
2015/03/19 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
js判断选择时间不能小于当前时间的示例代码
2013/09/24 Javascript
JavaScript中的undefined学习总结
2013/11/30 Javascript
2014 年最热门的21款JavaScript框架推荐
2014/12/25 Javascript
jQuery 判断图片是否加载完成方法汇总
2015/08/10 Javascript
使用Browserify来实现CommonJS的浏览器加载方法
2017/05/14 Javascript
Vue的MVVM实现方法
2017/08/16 Javascript
Mint UI 基于 Vue.js 移动端组件库
2017/11/07 Javascript
jQuery实现文字超过1行、2行或规定的行数时自动加省略号的方法
2018/03/28 jQuery
微信小程序文章详情页跳转案例详解
2019/07/09 Javascript
[02:05]2014DOTA2西雅图国际邀请赛 BBC第二天小组赛总结
2014/07/11 DOTA
[01:38]DOTA2第二届亚洲邀请赛中国区预选赛出线战队晋级之路
2017/01/17 DOTA
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
在Python 字典中一键对应多个值的实例
2019/02/03 Python
Mac 使用python3的matplot画图不显示的解决
2019/11/23 Python
使用Python3 poplib模块删除服务器多天前的邮件实现代码
2020/04/24 Python
python ETL工具 pyetl
2020/06/07 Python
python安装第三方库如xlrd的方法
2020/10/31 Python
英国灯具和灯泡网上商店:Lights.co.uk
2018/02/02 全球购物
全球最大的户外用品零售商之一:The House
2018/06/12 全球购物
L’Artisan Parfumeur官网:法国香水品牌
2020/08/11 全球购物
HR喜欢的自荐信格式
2013/10/08 职场文书
20岁生日感言
2014/01/13 职场文书
管理失职检讨书
2014/02/12 职场文书
物资采购方案
2014/06/12 职场文书
机关党员四风问题个人整改措施
2014/10/26 职场文书
个人政治思想总结
2015/03/05 职场文书
管理失职检讨书范文
2015/05/05 职场文书
2015年暑期见闻
2015/07/14 职场文书
python中requests库+xpath+lxml简单使用
2021/04/29 Python