不用括號也能呼叫? 設計一個接受模板字符串的函數吧! JavaScript

若你用過 styled-component ,肯定常把一長串的 CSS 放在 ` ` 之間,並且沒有包覆在 ( ) 裡頭,那函數是如何接收的呢?

realdennis
5 min readMar 13, 2019

讓我們一起來研究並設計一個接收模板字符串的函數!

文末 我會撰寫了一個與 styled 接受形式相仿的簡單小函數,依照 props value 決定 background-color 要 blue 還是 pink 。

我是萌新,什麼是 styled-component ?

styled-component 是一個允許你在模板字符裡頭輸入 CSS ,並且幫你產生對應樣式的組件,在React、Vue都能夠使用(vue-styled-components)。

styled-component 用起來是這個樣子

不過不用擔心,這篇並不是著重在 styled-component ,而是在這個一周有 67 萬下載量的函式庫中,追尋裡頭的魔法

第一次嘗試

想要挖掘深一點,不要先尋找答案,而是先試試看?

讓我們來定義一個函數,並把它所有傳進來的參數都印出來看看?

function logAll(...args){
console.log('印個東西來瞧瞧!',args)
}
logAll`hello!world`

來看看印出來的結果吧!

顯然後面的樣板字符串是真的能被函數所接收,而不用透過括號 () ,我們解決了一開始的問題,那我們再挖深一點,用樣板字符串的好處是什麼呢?為什麼不直接把樣板字符串像是變數一樣傳進去呢?

註: function fn(…args) 的用法會把 fn(1,2,3) 變成 args[0]=1args[1]=2 、…,這種解構並且把參數變成陣列操作的用法非常方便,更詳細的函數解構設計請看這篇《解構賦值 — 設計函數時的小技巧 JavaScript》。

尋找真理

我們先依照關鍵字去搜尋…「模板字符串」、「樣板字符 函數 參數」、….等等,可以找到 MDN 上的文章。

前面在介紹模板字符的用法,比如可以在模板字符裡面插入變數…等等的。

var father = {name:'Dio',age:100};
var friend = {name:'Mista',age:19}
// 以前古人的動態字串是這樣
console.log('我的爸爸叫做' + father.name + ',我的朋友叫做'+ friend.name);
// 模板字符串允許你這麼做:
console.log(`我的爸爸叫做${father.name},我的朋友叫做 ${friend.name}`);

讓我們繼續往下看。

標籤樣板字面值

(讓我偷懶引用一下 MDN 上面的解釋)

標籤樣板字面值是一種更高級的樣板字面值形式,允許你透過標籤函數操作樣板字面值的輸出。

  • 標籤函數的第一個參數是一字串陣列
  • 其餘參數則是處理過的表達式

最終,你可以返回一個經處理後的字串,甚至是完全不一樣的東西。

由於我覺得MDN舉得例子有點落落長(例子很棒啦,但不適合 Medium 閱讀),我直接寫一個精簡版的例子。

很顯然會回傳’za warudo’字串

隨便舉一個例子大概長這樣!

Exp1對應第一個被${}的、Exp2就是對應第二個${}。

styled-component 的文檔中其實也有針對這種標籤樣板的函數用法做介紹,而且標題下的非常有趣《The magic behind 💅 styled-components

這裡借用一張我覺得非常具象化的圖片。

src: https://mxstbr.blog/2016/11/styled-components-magic-explained/

一切都不是秘密

看來 styled-component 為什麼可以用 props 來決定如何改變樣式就不是什麼秘密了!

讓我們來寫一個可以接受參數的 CSS 吧!

尾聲

終於,我們不只搞懂了如何使用模板字串作為函數的輸入,而非天涯若比鄰的兩個括號 (………),而且也進一步搞懂了這樣傳遞參數後可以拿到不只字串本身,還能拿到表達式

由於我在尋找這個答案時,當時用幾個關鍵字無從下手,所以請允許我用幾個 hash tag 總結一下這篇的關鍵字,方便探求答案的人能挖掘到這篇文章:

#JavaScript #模板字符串 #樣板字面值 #函數設計 #函數參數 #styled #styledcomponent #react #ES6

類似問題如下

JavaScript 函數如何接受模板字串?

JavaScript 函數設計 `` 反引號?

JavaScript 函數 沒有括號 styled

JavaScript tag function

--

--

No responses yet