テンプレートストリングで関数実行
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ fn `a` で関数が実行されます
◆ String.raw `\n` で \n のまま取り出せます
◆ あとからデータを埋め込むタイプの使いまわせるテンプレートを作りました
◆ String.raw `\n` で \n のまま取り出せます
◆ あとからデータを埋め込むタイプの使いまわせるテンプレートを作りました
テンプレートストリングで関数が実行される
テンプレートストリングの前に関数があるときにおかしな動きをしていたのを調べてみました() がなくても関数が実行されてるようです
そのせいで ; 書かない書き方してるとエラーが出てたようです
ですが 関数を普通に実行してるのとは違うようです
var dump = (...args) => {console.log(args)}
var result = dump `abcdefg`
console.log(result)
var result = dump `abcdefg`
console.log(result)
0: Array[1]
0: "abcdefg"
length: 1
raw: Array[1]
0: "abcdefg"
length: 1
__proto__: Array[0]
__proto__: Array[0]
length: 1
__proto__: Array[0]
undefined
0: "abcdefg"
length: 1
raw: Array[1]
0: "abcdefg"
length: 1
__proto__: Array[0]
__proto__: Array[0]
length: 1
__proto__: Array[0]
undefined
var dump = (...args) => {console.log(args)}
var result = dump `A ${"B"} C${1+1}D${Math.random()}`
console.log(result)
var result = dump `A ${"B"} C${1+1}D${Math.random()}`
console.log(result)
0: Array[4]
0: "A "
1: " C"
2: "D"
3: ""
length: 4
raw: Array[4]
0: "A "
1: " C"
2: "D"
3: ""
length: 4
__proto__: Array[0]
__proto__: Array[0]
1: "B"
2: 2
3: 0.1894653243944049
length: 4
__proto__: Array[0]
undefined
0: "A "
1: " C"
2: "D"
3: ""
length: 4
raw: Array[4]
0: "A "
1: " C"
2: "D"
3: ""
length: 4
__proto__: Array[0]
__proto__: Array[0]
1: "B"
2: 2
3: 0.1894653243944049
length: 4
__proto__: Array[0]
undefined
テンプレートへの埋め込みの ${} の前後で文字列が分割されて第一引数に入っています
2 つめ以降の引数は ${} 内が評価された後の値が入ってます
関数の実行は 式 なので 返り値があります
関数の返り値がそのまま受け取れるようです
var result = (()=>"dummy") `abcd`
console.log(result)
console.log(result)
dummy
関数の後ろにカッコなしで文字列書いて実行されるって 別の言語使ってるみたいですね
raw
第一引数は配列ですが raw というプロパティが存在しています上の例では 全く同じものですが エスケープされない特徴があります
((e)=>{console.log(e)}) `ab\tcd\n\nef
g
hij\tkl`
g
hij\tkl`
0: "ab cd↵↵ef↵g↵↵h ij kl"
length: 1
raw: Array[1]
0: "ab\tcd\n\nef↵g↵↵h ij\tkl"
length: 1
__proto__: Array[0]
__proto__: Array[0]
length: 1
raw: Array[1]
0: "ab\tcd\n\nef↵g↵↵h ij\tkl"
length: 1
__proto__: Array[0]
__proto__: Array[0]
raw じゃない方をみると 普通の文字列なので \t や \n はタブや改行に置き換えられてます
raw では \t は \t で \n は \n でそのままです
書いたとおりに取得できます
raw でも直接改行やタブを入力していたものは そのまま改行になっています
なにか作ってみる
その1
便利そうな機能なので何か作れそうですvar raw = e => e.raw[0]
console.log(raw `a\nb\nc`)
console.log(raw `a\nb\nc`)
a\nb\nc
\n などをそのまま表示できて便利です
ですが ググると String.raw で同じことができるらしいです
String.raw `a\n${1}b\n${2}c`
a\n1b\n2c
ネイティブでやってるなら ${} あってもできるかなとやってみたらできました
String.raw との組み合わせは覚えておくと良さそうです
その2
せっかく作ったのがすでにあったので別のことを考えてみます考えてみればテンプレートストリングってテンプレートストリングという名前なのにテンプレートを保存しておいて使い回すものじゃなくてその場でテンプレート形式で書いて埋め込むものですよね
じゃあ使いまわせるようにしようか
function Template(parts, ...names){
var obj = {
parts,
names
}
obj.__proto__ = Template.prototype
return obj
}
Template.prototype.generate = function(elements){
if(Array.isArray(elements)){
return this.parts.alternate(elements.slice(0, this.names.length)).join("")
}else{
return this.parts.alternate(this.names.map(e => elements[e])).join("")
}
}
var obj = {
parts,
names
}
obj.__proto__ = Template.prototype
return obj
}
Template.prototype.generate = function(elements){
if(Array.isArray(elements)){
return this.parts.alternate(elements.slice(0, this.names.length)).join("")
}else{
return this.parts.alternate(this.names.map(e => elements[e])).join("")
}
}
こんな風にテンプレートを作ります
var template = Template `(${"test"}) [${"sample"}] "${"name"}"`
埋め込むときはこんな風に指定した名前のオブジェクトを渡します
var result = template.generate({
test: "てすと",
sample: "さんぷる",
name: "なまえ"
})
console.log(result)
test: "てすと",
sample: "さんぷる",
name: "なまえ"
})
console.log(result)
(てすと) [さんぷる] "なまえ"
配列で渡せば前から順に入ります
var result = template.generate([123,456,7890])
console.log(result)
console.log(result)
(123) [456] "7890"
便利なんですが 名前がテンプレートストリングなわけですし (その1)の String.raw みたいにまだ私が見つけてないだけでそんな機能ありそうな予感がすごくします
上では省略しましたが 配列を交互にマージする Array#alternate はこんなです
Array.prototype.alternate = function(...arrs){
var res = []
arrs.unshift(this)
for(var i=0, precount=-1;precount!==(precount=res.length);i++){
for(var j=0;j<arrs.length;j++){
var arr = arrs[j]
i < arr.length && res.push(arr[i])
}
}
return res
}
var res = []
arrs.unshift(this)
for(var i=0, precount=-1;precount!==(precount=res.length);i++){
for(var j=0;j<arrs.length;j++){
var arr = arrs[j]
i < arr.length && res.push(arr[i])
}
}
return res
}
今回限定なら reduce でサッとやってもよさそうでしたが せっかくなので汎用的に使えそうな形にしました