
神秘的語(yǔ)法
一直覺(jué)得 JS 是門神奇的語(yǔ)言,使用者不需要完全知曉底層概念,簡(jiǎn)單項(xiàng)目者甚至不需要會(huì)用這門語(yǔ)言就能使用它完成大大小小的項(xiàng)目。語(yǔ)言作者們將其設(shè)計(jì)的太好用,很多的開發(fā)者對(duì)于一些基礎(chǔ)概念都不求甚解。其中有一個(gè)很經(jīng)典的問(wèn)題是涉及到 .call() 這個(gè)方法在算法題中的應(yīng)用。
如果你也是將 JS 作為主力語(yǔ)言的前端攻城獅們,不知道你們有沒(méi)遇到過(guò)想實(shí)現(xiàn)某種功能卻無(wú)從下手的感覺(jué),最近在學(xué)習(xí)《你不知道的JavaScript》這本書的時(shí)候,果不其然遇到了我既熟悉又陌生的 [].slice.call(args) 語(yǔ)法的應(yīng)用。
想要往更深處行走,這些以前覺(jué)得晦澀的語(yǔ)法看起來(lái)也是避不開了。
不熟不吃
很多老師都會(huì)這么教,無(wú)論學(xué)習(xí)什么,都要先找到自己熟悉的部分下手。
乍一看,這個(gè)東西其實(shí)我是認(rèn)識(shí)的鴨,分解開來(lái)除了 call 以外都是很經(jīng)常用到的東西(.call其實(shí)也很常用,一般將 call 方法用于強(qiáng)制指定 this 的指向)
[ ]
乍一想,中括號(hào)??
貌似在 JS 里我們見(jiàn)到的 [] 更多是作為數(shù)組的形式出現(xiàn)的
馬克思爺爺說(shuō)過(guò)實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)
那么我們就來(lái)看看它們之間的關(guān)系吧!
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結(jié)果為object,因?yàn)锳rray也是Object
//"[object Array]"
[] instanceof Array
//true
從上面測(cè)試的結(jié)果可以看出 [] 果然就是數(shù)組本數(shù)了,其本身的屬性只有 length,但是其可以通過(guò)數(shù)組原型繼承到所有數(shù)組應(yīng)該有的方法。
.slice
從上一個(gè) [] 的測(cè)試?yán)镂覀兛梢郧逦吹?slice 方法存在于數(shù)組的原型鏈中,所以我們可以推測(cè)此 slice 就是彼 slice 了。
[].slice === Array.prototype.slice
//true
答案跟我們預(yù)想的完全一樣,但是 [] 本身并沒(méi)有 slice 這個(gè)方法,所以其是通過(guò)原型鏈查找得到的這個(gè)方法。
可能有的同學(xué)也不怎么經(jīng)常用 slice 這里搬運(yùn)一下文檔:

傳送門 >>>>JavaScript中的數(shù)組slice方法
.call
有關(guān) call 的用法可參照另一篇文章>>>>this用法
call 方法的作用其實(shí)就是主動(dòng)綁定 this 的指向。
[].slice.call(args)的使用
看到這里可能有人會(huì)問(wèn),不是還沒(méi)介紹 args 嗎?
這里的 args 只是一個(gè)占位符,并不是一個(gè)有意義的標(biāo)記項(xiàng)。寫成 args 是因?yàn)檫@種用法常用于將函數(shù)接收的參數(shù)分割存到數(shù)組里,占位符由此得名。
好了,結(jié)合上面我們的分解所得,串起來(lái)看一下這一個(gè)魔法是怎么工作的吧!
args 的 this 會(huì)被強(qiáng)制綁定至 [] 也即數(shù)組的原型鏈上,由此可以使用數(shù)組中含有的 slice 方法。
但是通常傳入的 args 應(yīng)該是預(yù)想中的數(shù)據(jù)類型,以保證函數(shù)的順利運(yùn)行,否則會(huì)發(fā)生很多難以定位的錯(cuò)誤。
下面我們來(lái)實(shí)驗(yàn)一下吧!
//一個(gè)經(jīng)典的使用場(chǎng)景是獲取函數(shù)中的auguments對(duì)象
function test(){
var args = [].slice.call( arguments )
console.log( args );
}
test( 'hello', '111' );
// ["hello", "111"]
總結(jié)
溫故而知新,??闯P?。
很多深入語(yǔ)言內(nèi)部機(jī)制的用法可能我們極少用到,但是一旦遇到可能會(huì)卡掉我們大量寶貴的工作時(shí)間。
更有甚者很多開發(fā)者對(duì)于自己不熟悉的領(lǐng)域敬而遠(yuǎn)之,現(xiàn)在的JS有點(diǎn)像我們開電燈時(shí)的操作,只知道按下開關(guān)會(huì)亮起一盞明亮的燈,而從未深入燈內(nèi)部進(jìn)行探究。
Clancy Lin
2019.2.8
I can be whatever I want to be