配列のメソッドが増えてた
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ entries
◆ keys
◆ fill
◆ copyWithin
◆ keys
◆ fill
◆ copyWithin
Chrome でコード書いてると 予測変換で使えるメソッドが出ますよね
あそこで普段みないものがいくつか増えてました
先に書いておきます
いつものことですが とりあえず使ってみた紹介ですので イチイチMDNのリファレンスとか見ないで とりあえず Chrome でそれっぽい感じに動かして動いた という判断です
引数に何かいれるとかまた違う動きするかもとか もっと良い使い方あるかもとかはありえます
classList が便利すぎる
イテレータが返ってくるやつです
こんな感じに使えます
Ecma6 で追加されると言われてた for of で使えます
直接 next メソッド でも使えるようです
value が 2 のときに次がないって教えてくれたほうが良いような気もしますがこんな仕様らしいです
done が true でも next メソッドは何回呼んでも呼べますが 結果は一緒です
イテレータの説明みたいになってますけど keys では 配列のキー (添字) のイテレータが返って来ます
Chrome での確認ですが ArrayIterator のインスタンスという扱いでした
配列なら keys より values のほうが大切そうなんですけど なぜ keys があって values がないのかはわからないです
entries があれば values なくてもいいとはいえますけどそれなら keys だっていらないと思いますし
第二引数と第三引数で範囲選択もできます
slice と一緒です
初期化が簡単になりますね
いままで
前半が気持ち悪いなら
map のときは length を変えても実際にデータがないので 何も起きませんでしたが fill では length に合わせてやってくれるので これでちゃんと初期化されます
map だとこうなっていました
length の指定を Array 関数でしてしまえばもっと省略して書くことが出来ます
map はデータがないと実行されませんでしたが fill を一度実行することでデータができるので こんな風に指定回数の繰り返しを for 文を使わずににかけます
何が起きてるかの理解に時間がかかりました
fill のときと同じく 第二引数と第三引数で slice した配列で今の配列を上書きします
上書きする開始位置を第一引数で指定します
上書きなので 自分自身が変更されます
返り値も一緒の値です
元の配列の長さは変わりません
中身を自分実装するならこんな感じでしょうか
イテレータを返す2つのメソッドはChrome44でも使えましたが fill と copyWithin メソッドはChrome45からでした
Chrome46では特に増えてないみたいです
あそこで普段みないものがいくつか増えてました
先に書いておきます
いつものことですが とりあえず使ってみた紹介ですので イチイチMDNのリファレンスとか見ないで とりあえず Chrome でそれっぽい感じに動かして動いた という判断です
引数に何かいれるとかまた違う動きするかもとか もっと良い使い方あるかもとかはありえます
keys
keys はこの記事で軽く触れたやつですclassList が便利すぎる
イテレータが返ってくるやつです
こんな感じに使えます
var a = [1,2,3].keys()
for(var v of a){
console.log(v)
}
console.log("これ以上は出力されない")
for(var v of a){
console.log(v)
}
for(var v of a){
console.log(v)
}
console.log("これ以上は出力されない")
for(var v of a){
console.log(v)
}
0
1
2
これ以上は出力されない
1
2
これ以上は出力されない
Ecma6 で追加されると言われてた for of で使えます
直接 next メソッド でも使えるようです
var a = [1,2,3].keys()
console.log(a.next()) // Object {value: 0, done: false}
console.log(a.next()) // Object {value: 1, done: false}
console.log(a.next()) // Object {value: 2, done: false}
console.log(a.next()) // Object {value: undefined, done: true}
console.log(a.next()) // Object {value: undefined, done: true}
done というプロパティが true になったら終わってるようですconsole.log(a.next()) // Object {value: 0, done: false}
console.log(a.next()) // Object {value: 1, done: false}
console.log(a.next()) // Object {value: 2, done: false}
console.log(a.next()) // Object {value: undefined, done: true}
console.log(a.next()) // Object {value: undefined, done: true}
value が 2 のときに次がないって教えてくれたほうが良いような気もしますがこんな仕様らしいです
done が true でも next メソッドは何回呼んでも呼べますが 結果は一緒です
イテレータの説明みたいになってますけど keys では 配列のキー (添字) のイテレータが返って来ます
Chrome での確認ですが ArrayIterator のインスタンスという扱いでした
entries
次もイテレータを返してくれるメソッドですvar a = [1,2,3].entries()
for(var v of a){
console.log(v)
}
for(var v of a){
console.log(v)
}
[0, 1]
[1, 2]
[2, 3]
key と value のペアが配列になってます[1, 2]
[2, 3]
values はいまのところないです
classList にあった values はなかったです配列なら keys より values のほうが大切そうなんですけど なぜ keys があって values がないのかはわからないです
entries があれば values なくてもいいとはいえますけどそれなら keys だっていらないと思いますし
fill
これは実際の結果をみるとわかりやすいです[1,2,3].fill(100) // [100,100,100]
全部の値を指定の要素に置き換えてくれます第二引数と第三引数で範囲選択もできます
["a","b","c","d","e"].fill(1,2,4) // ["a", "b", 1, 1, "e"]
第三引数は 数じゃなくて終わりの場所の index なようですslice と一緒です
初期化が簡単になりますね
いままで
Array.apply(null, Array(10)).map(function(){return 1})
だったのがArray.apply(null, Array(10)).fill(1) // [1,1,1,1,1,1,1,1,1,1]
で済みます前半が気持ち悪いなら
a = []
a.length = 10
a.fill(1) // [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
でもできますa.length = 10
a.fill(1) // [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
map のときは length を変えても実際にデータがないので 何も起きませんでしたが fill では length に合わせてやってくれるので これでちゃんと初期化されます
map だとこうなっていました
a = []
a.length = 10
a.map(function(){return 1}) // [undefined × 10]
a.length = 10
a.map(function(){return 1}) // [undefined × 10]
length の指定を Array 関数でしてしまえばもっと省略して書くことが出来ます
Array(10).fill(1) // [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
map はデータがないと実行されませんでしたが fill を一度実行することでデータができるので こんな風に指定回数の繰り返しを for 文を使わずににかけます
Array(10).fill().forEach((e, i) => {
document.body.appendChild(document.createElement("div"))
})
range 関数がないので 代わりにdocument.body.appendChild(document.createElement("div"))
})
Array(100).fill().map((e, i) => i * 2 + 100)
// [100, 102, 104, ..., 296, 298]
こうやって 100 から始まって step=2 の長さ 100 の配列を作るということもできます// [100, 102, 104, ..., 296, 298]
copyWithin
分かりづらい動きをするメソッドです何が起きてるかの理解に時間がかかりました
fill のときと同じく 第二引数と第三引数で slice した配列で今の配列を上書きします
上書きする開始位置を第一引数で指定します
上書きなので 自分自身が変更されます
返り値も一緒の値です
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(1, 2, 4)
< [0, 2, 3, 3, 4, 5, 6, 7, 8, 9]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(5, 0)
< [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(5, 8)
< [0, 1, 2, 3, 4, 8, 9, 7, 8, 9]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(0, 5)
< [5, 6, 7, 8, 9, 5, 6, 7, 8, 9]
こうなります< [0, 2, 3, 3, 4, 5, 6, 7, 8, 9]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(5, 0)
< [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(5, 8)
< [0, 1, 2, 3, 4, 8, 9, 7, 8, 9]
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].copyWithin(0, 5)
< [5, 6, 7, 8, 9, 5, 6, 7, 8, 9]
元の配列の長さは変わりません
中身を自分実装するならこんな感じでしょうか
Array.prototype.copywithin = function(pasteStart, cutStart, cutEnd){
var slice = this.slice(cutStart, cutEnd)
for(var i=0;i<slice.length;i++){
var target_idx = pasteStart + i
if(target_idx >=0 && target_idx < this.length){
this[target_idx] = slice[i]
}
}
return this
}
最近の書き方っぽくvar slice = this.slice(cutStart, cutEnd)
for(var i=0;i<slice.length;i++){
var target_idx = pasteStart + i
if(target_idx >=0 && target_idx < this.length){
this[target_idx] = slice[i]
}
}
return this
}
Array.prototype.copywithin = function(pasteStart, cutStart, cutEnd){
this.slice(cutStart, cutEnd).some((e, i) =>{
var target_idx = pasteStart + i
if(target_idx < 0) return false
if(target_idx >= this.length) return true
this[target_idx] = e
})
return this
}
this.slice(cutStart, cutEnd).some((e, i) =>{
var target_idx = pasteStart + i
if(target_idx < 0) return false
if(target_idx >= this.length) return true
this[target_idx] = e
})
return this
}
イテレータを返す2つのメソッドはChrome44でも使えましたが fill と copyWithin メソッドはChrome45からでした
Chrome46では特に増えてないみたいです