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 相关文章推荐
基于prototype的validation.js发布2.3.4新版本,让你彻底脱离表单验证的烦恼
Dec 06 Javascript
javascript 图片上传预览-兼容标准
Jun 01 Javascript
jQuery中append、insertBefore、after与insertAfter的简单用法与注意事项
Apr 04 Javascript
JS 面向对象之神奇的prototype
Feb 26 Javascript
由Javascript实现的页面日历
Nov 04 Javascript
js控制href内容的连接内容的变化示例
Apr 30 Javascript
jQuery页面加载初始化常用的三种方法
Jun 04 Javascript
JavaScript中数据结构与算法(一):栈
Jun 19 Javascript
jQuery得到多个值只能用取Class ,不能用取ID的方法
Dec 04 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
Mar 08 Javascript
Vue实现将数据库中带html标签的内容输出(原始HTML(Raw HTML))
Oct 28 Javascript
基于JavaScript实现十五拼图代码实例
Apr 26 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
索尼SONY SRF-S83/84电路分析和打磨
2021/03/02 无线电
PHP 如何向 MySQL 发送数据
2006/10/09 PHP
PHP中可以自动分割查询字符的Parse_str函数使用示例
2014/07/25 PHP
php字符串替换函数substr_replace()用法实例
2015/03/17 PHP
PHP简单实现冒泡排序的方法
2016/12/26 PHP
PHP7 其他语言层面的修改
2021/03/09 PHP
JavaScript OOP类与继承
2009/11/15 Javascript
JQuery扩展插件Validate—4设置错误提示的样式
2011/09/05 Javascript
JavaScript实现url地址自动检测并添加URL链接示例代码
2013/11/12 Javascript
分享自己用JS做的扫雷小游戏
2016/02/17 Javascript
安装使用Mongoose配合Node.js操作MongoDB的基础教程
2016/03/01 Javascript
JS基于ocanvas插件实现的简单画板效果代码(附demo源码下载)
2016/04/05 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
2016/06/03 Javascript
JavaScript直播评论发弹幕切图功能点集合效果代码
2016/06/26 Javascript
Vue.js双向绑定实现原理详解
2016/12/22 Javascript
jQuery实现Select下拉列表进行状态选择功能
2017/03/30 jQuery
jquery.validate表单验证插件使用详解
2017/06/21 jQuery
layui实现点击按钮给table添加一行
2018/08/10 Javascript
react build 后打包发布总结
2018/08/24 Javascript
在layui中使用form表单监听ajax异步验证注册的实例
2019/09/03 Javascript
微信小程序和H5页面间相互跳转代码实例
2019/09/19 Javascript
javascript实现留言板功能
2020/02/08 Javascript
详解JS预解析原理
2020/06/16 Javascript
[01:07:53]RNG vs VG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
Flask的图形化管理界面搭建框架Flask-Admin的使用教程
2016/06/13 Python
Python实现的选择排序算法原理与用法实例分析
2017/11/22 Python
python打包exe开机自动启动的实例(windows)
2019/06/28 Python
python给指定csv表格中的联系人群发邮件(带附件的邮件)
2019/12/31 Python
python drf各类组件的用法和作用
2021/01/12 Python
selenium如何定位span元素的实现
2021/01/13 Python
匡威意大利官方商店 :Converse意大利
2018/11/27 全球购物
英国景点门票网站:attractiontix
2019/08/27 全球购物
渡河少年教学反思
2014/02/12 职场文书
房地产广告词大全
2014/03/19 职场文书
新春文艺演出主持词
2014/03/27 职场文书
Android 界面一键变灰 深色主题工具类
2022/04/28 Java/Android