原文: https://zswfx.com/articles/5dc8f64a9cf7c17b240e5c6c
我们经常在函数参数里面使用如下操作 Array.prototype.slice.call(arguments, 1)
, 这样的操作,类似还有 Object.prototype.toString.apply(o)
这种操作,为什么可以这样玩呢?
前言
我们经常通过数组的方法去操作类数组,还会使用一些JS对象的方法来获取一个对象的真实的构造函数对象名称。考虑类数组不是一个数组,是一个对象类似如下:
{
"0": "b",
"1": "a",
"length": 2
}
这样就可以使用,为什么呢?
探索
为了搞清上面问题,我们就需要从两个方面入手:
- call/apply 定义
- Array.prototype.slice、Object.prototype.toString
第一个需要找一下call/apply 调用流程,第二个看看规范如何定义这些方法
就已apply 为例(call类似), 具体方法以slice和toString为例
apply 规范
使用apply方法,有两个作用
- 1-8 处理通过 apply 方法传入的参数
- 9 处理改变函数的this值,并调用函数
上面调用函数,我们接下来就继续看看函数如何处理
Array.prototype.slice
通过规范可以看出,Array也是通过key值获取的,在第10步中可以看到循环获取对象值,通过对象 [[Get]]
的方式来获取。
在每个数组方法后面,我们可以看到这样一句话:
使用数组的所有方法,不一定要求对象是数组,只要符合能够通过递增的key值可以获取的类数组对象即可使用.
下面继续看看 toString
toString
我们正常使用 Object.prototype.toString.apply({})
的结果是 [object Object]
. 上面是规范结果
- 第1步,确定 undefined 值为
[object Undefined]
- 第2步,确定 null 值为
[object Null]
, - 第3步,通过内部方法
toObject
得到结果 (稍后说明toObject方法) - 第4步,获取内部
[[Class]]
值 - 第5步,拼接字符串
[object
、[[Class]]
,]
返回结果
由此可得知,我们得到结果其实也是引擎根据规范来处理的。
toObject
toObject 的结果就是返回原始值(Primive Value)的盒装对象(box model object).
最后 [[Class]]
的获取结果是一个说明对象分类名称的字符串。
最后
最近探索规范,发现越来越多想法和只是和规范一一验证。探索规范过程也是一种进步过程,任何小的改变,都是有迹可循,任何东西都来自规范。正如有理论支持的代码,才是坚不可摧,否则就如同一盘散沙。
欢迎交流.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。