神秘的语法
一直觉得 JS 是门神奇的语言,使用者不需要完全知晓底层概念,简单项目者甚至不需要会用这门语言就能使用它完成大大小小的项目。语言作者们将其设计的太好用,很多的开发者对于一些基础概念都不求甚解。其中有一个很经典的问题是涉及到 .call() 这个方法在算法题中的应用。
如果你也是将 JS 作为主力语言的前端攻城狮们,不知道你们有没遇到过想实现某种功能却无从下手的感觉,最近在学习《你不知道的JavaScript》这本书的时候,果不其然遇到了我既熟悉又陌生的 [].slice.call(args) 语法的应用。
想要往更深处行走,这些以前觉得晦涩的语法看起来也是避不开了。
不熟不吃
很多老师都会这么教,无论学习什么,都要先找到自己熟悉的部分下手。
乍一看,这个东西其实我是认识的鸭,分解开来除了 call 以外都是很经常用到的东西(.call其实也很常用,一般将 call 方法用于强制指定 this 的指向)
[ ]
乍一想,中括号??
貌似在 JS 里我们见到的 [] 更多是作为数组的形式出现的
马克思爷爷说过实践是检验真理的唯一标准
那么我们就来看看它们之间的关系吧!
Object.getOwnPropertyNames( [] )
//["length"]
Object.getOwnPropertyNames( Array.prototype )
//(37) ["length", "constructor", "concat", "pop", "push", "shift", "unshift", "slice", "splice", "includes", "indexOf",
//"keys", "entries", "forEach", "filter", "map", "every", "some", "reduce", "reduceRight", "toString",
//"toLocaleString", "join", "reverse", "sort", "lastIndexOf", "copyWithin", "find", "findIndex", "fill", "remove",
//"removeFirstIf", "removeIf", "repeat", "last", "lastDef", "clone"]
Object.prototype.toString.call( [] )
//查看[]的类型
//若直接typeOf结果为object,因为Array也是Object
//"[object Array]"
[] instanceof Array
//true
从上面测试的结果可以看出 [] 果然就是数组本数了,其本身的属性只有 length,但是其可以通过数组原型继承到所有数组应该有的方法。
.slice
从上一个 [] 的测试里我们可以清晰看到 slice 方法存在于数组的原型链中,所以我们可以推测此 slice 就是彼 slice 了。
[].slice === Array.prototype.slice
//true
答案跟我们预想的完全一样,但是 [] 本身并没有 slice 这个方法,所以其是通过原型链查找得到的这个方法。
可能有的同学也不怎么经常用 slice 这里搬运一下文档:
传送门 >>>>JavaScript中的数组slice方法
.call
有关 call 的用法可参照另一篇文章>>>>this用法
call 方法的作用其实就是主动绑定 this 的指向。
[].slice.call(args)的使用
看到这里可能有人会问,不是还没介绍 args 吗?
这里的 args 只是一个占位符,并不是一个有意义的标记项。写成 args 是因为这种用法常用于将函数接收的参数分割存到数组里,占位符由此得名。
好了,结合上面我们的分解所得,串起来看一下这一个魔法是怎么工作的吧!
args 的 this 会被强制绑定至 [] 也即数组的原型链上,由此可以使用数组中含有的 slice 方法。
但是通常传入的 args 应该是预想中的数据类型,以保证函数的顺利运行,否则会发生很多难以定位的错误。
下面我们来实验一下吧!
//一个经典的使用场景是获取函数中的auguments对象
function test(){
var args = [].slice.call( arguments )
console.log( args );
}
test( 'hello', '111' );
// ["hello", "111"]
总结
温故而知新,常看常新。
很多深入语言内部机制的用法可能我们极少用到,但是一旦遇到可能会卡掉我们大量宝贵的工作时间。
更有甚者很多开发者对于自己不熟悉的领域敬而远之,现在的JS有点像我们开电灯时的操作,只知道按下开关会亮起一盏明亮的灯,而从未深入灯内部进行探究。
Clancy Lin
2019.2.8
I can be whatever I want to be