Chapter 5. Working with Arrays and Loops
2010/08/03(火) 25:36 Javascript親記事へこのエントリーをはてなブックマークに追加

5.0  Introduction

配列要素の作り方 new Arrayと[]リテラルの話。
配列作成時に空の場合はundefinedになる。new Array(数)で空の配列を作れる。
var arrLiteral = ["val1",,"val3"];
arrLiteral[1]; // undefined
var largeCollection = new Array(100); // 100個のundefinedからなる空の配列

5.2  Creating a Multidimensional Array

多次元配列の話
Arrayを[index]で指定せず呼びだした時に自動でtoStringされる。
そのとき多次元配列だとindexの若い順にくっつけたものが表示される。
// set array length
var arrayLength = 3;
// create array
var multiArray = new Array(arrayLength);
for (var i = 0; i < multiArray.length; i++) {
  multiArray[i] = new Array(arrayLength);
}
// add items to first array index
multiArray[0][0] = "apple";
multiArray[0][1] = "banana";
multiArray[0][2] = "cherry";
// second
multiArray[1][0] = 2;
multiArray[1][1] = 56;
multiArray[1][2] = 83;
// third
multiArray[2][0] = ['test','again'];
multiArray[2][1] = ['Java','script'];
multiArray[2][2] = ['read','books'];
alert(multiArray[2]); // prints out test,again,Java,script,read,books
alert(multiArray[2][2]); // prints out read,books
alert(multiArray[2][2][1]); // prints out books

5.4  Sorting an Array

sort関数について。
sort関数は引数なしだと辞書順のソートを行う。
var numberArray = [4,13,2,31,5];
alert(numberArray.sort()); // returns  13,2,31,4,5 辞書順になっている
ソート順を定義する関数を引数にとれば数値を比較したsortができる。
function compareNumbers(a,b) {
   return a - b;
}
var numArray = [13,2,31,4,5];
alert(numArray.sort(compareNumbers)); // prints 2,4,5,13,31
compareNumbersをもっと明確にすると多分こんな感じ。
function compareNumbers(a,b) {
    if((a - b) > 0){
        // aの方が大きい、b,aの順にする
        return 1;
    }else if((a - b) < 0){
        // bの方が大きい、a,bの順にする
        return -1;
    }else if((a - b) == 0){
        // 同じくらいなので、交換しない
        return 0;
    }
}

sort - MDC

5.5  Store and Access Values in Order
5.6  Store and Access Values in Reverse Order
配列から要素を取り出す際にFIFO的な取り出しはshift()、LIFO的な取り出しはpop()。
先頭から取り出すのがshift()、後ろから取り出すのがpop()

5.7  Create a New Array as a Subset of an Existing Array

Arrayに対してsliceをするとその間をとりだした配列ができる。
var origArray = new Array(4);
origArray[0] = new Array("one","two");
origArray[1] = new Array("three","four");
origArray[2] = new Array("five","six");
origArray[3] = new Array("seven","eight");
// create new array using slice
var newArray = origArray.slice(1,3);
newArray// newArray[1]から[3]が取り出されるので、three,four,five,six

5.8  Searching Through an Array

ECMAscript 5では、Arrayから一致する要素を検索するにはindexOfとlastIndexOfが使えます。
StringのindexOfと違って完全一致===でtrueなもののindexが返ってくる。第二引数で探索を始める位置が指定できる。
IE8以外のブラウザは使えるそうです。
var animals = new Array("1","cat","seal","walrus","lion", "cat");
alert(animals.indexOf(1)); // prints -1 型が違うので-1
alert(animals.indexOf("ca")); // prints -1 マッチしないので-1
alert(animals.indexOf("cat",2)); // prints 5
alert(animals.lastIndexOf("cat",4)); // prints 1
indexOf - MDC にArray.prototype.indexOfの定義が乗っています。(ちゃんと===で比較している)

5.9  Flatten a Multidimensional Array

多次元配列になっているものをフラットにして1次元の配列にする。
var origArray = new Array();
origArray[0] = new Array("one","two");
origArray[1] = new Array("three","four");
origArray[2] = new Array("five","six");
origArray[3] = new Array("seven","eight");
// flatten array
var newArray = origArray[0].concat(origArray[1],origArray[2],origArray[3]);
alert(newArray); // 配列を平らに結合した配列
// こうした方がシンプルかも。
var newArray2 = Array.concat.apply(null,origArray);
alert(newArray2); // 配列を平らに結合した配列-上と同じ意味

5.10  Search and Remove or Replace Array Elements

配列から要素を除去、置換を行うにはArray.spliceが使える。
Array.spliceは古い要素を取り除きつつ新しい要素を追加するので実際には置換とは微妙に違う。
第一引数から第二引数で書いた分だけ配列からremoveする。そして第三引数以降の要素を除去した部分に追加する。
array.splice(index, howMany, [element1][, ..., elementN]);
var animals = new Array("dog","cat","seal","walrus","lion","cat");
// 配列から要素を削除
animals.splice(animals.indexOf("walrus"),1); // dog,cat,seal,lion,cat
// 配列の要素を置換
// 厳密に言えば削除→追加の流れ
animals.splice(animals.lastIndexOf("cat"),1,"monkey"); // dog,cat,seal,lion,monkey
// 第三引数移行が追加される
animals.splice(animals.lastIndexOf("dog"),1,"ebi","kani");// ebi,kani,cat,seal,lion,monkey
splice - MDC
spaderMonkeyだけ第二引数を省略して第一引数以降を除去する書き方もできる。
Array.indexOfとspliceはIE8では動きませんよ。
Array.spliceはIEでも動きます。(本が間違ってる)
こっからよくあるArrayの新しいメソッドの話。(ECMAScript 5標準で使える)
JavaScript 配列 (Array) の反復的なメソッド : Serendip - Webデザイン・プログラミング
まずはforEachとmapの違い

5.11  Applying a Function Against Each Array Element

与えられた関数を、配列の各要素に対して一度ずつ実行する。
forEachを使えば、配列の中でマッチしたものをどんどん置換していくみたいな処理が簡単に書けるよ。
配列の要素が"ab"だったら"**"にする。
var charSets = new Array("ab","bb","cd","ab","cc","ab","dd","ab");
function replaceElement(element,index,array) {
   if (element == "ab") array[index] = "**";
}
// apply function to each array element
charSets.forEach(replaceElement);
alert(charSets); // prints **,bb,cd,**,cc,**,dd,**
forEachに使うfunctionには3つの引数が渡されるけど、これが覚えづらいと思う。
普通のfor文でも同じ処理はできるので、この辺を簡単に理解できる方法が必要。

「elmほしいよねー, iterationだもんねー. -> indexもほしくね? -> arrayもほしい? thisがあるじゃん -> 第2引数でthis束縛しちゃったって? 仕方ないなあ. ほれよ.」っていう具合に引数が増えていったものとストーリー仕立てで考えている...


Twitter / utatane: 「elmほしいよねー, iterationだもんねー ...

IE8では動かないけど、forEach - MDC に Array.prototype.forEachがうんぬん。

5.12  Applying a Function to Every Element in an Array and Returning a New Array

与えられた関数を配列の各要素に対して一度ずつ実行、その結果からなる新しい配列を生成。
forEachは元々の配列にfunctionを適応するので破壊的に変更しますが、mapはfunctionを適応した新しい配列を返す。それ以外はforEachと同じ。
map - MDCで詳しく書いてある。
forEachとmapのdiffを比べるとやっていることが明確になる。mapはnew Arrayして新しく配列を作ってそれを返していることが分かる。

filterは配列をフィルタリングしてtrueとなるものだけでできた新しい配列を返す。
everyは配列がテスト関数ですべてtrueならtrue、falseが混じってたらfalseを返すテストメソッド。
someとかは省かれたのでArray - MDCを見る。

5.15  Using an Associative Array to Store Form Element Names and Values

連想配列をJavaScriptで書くときはArrayではなくObjectを使う。
連想配列の中身を見るのにはfor inを使うが、for in は配列走査のためではないってやつ。
JavaScript の配列と連想配列の違い - IT戦記
Googleさんも連想配列をArrayでやるなって言ってた Google JavaScript Style Guideの記録
Array.prototype.hoge = function(){
    // Array.prototypeが拡張されている
};
var ary = new Array();
ary["jp"]="日本";
ary["us"]="アメリカ";
ary["ye"]="イエメン";
for (var i in ary) {
  p(i);// hoge ye us jp  hogeが混じる
}
ただし上の例はObjectが拡張されていると、オブジェクトリテラルで連想配列を作っても同じ結果になってしまう。
最速インターフェース研究会 :: prototype.jsのObject汚染を回避する方法
連想配列の危険性 Painfully Obvious → Blog Archive → JavaScript “Associative Arrays” Considered Harmful


やりすぎた拡張は「プロトタイプ汚染」と呼ばれます。JavaScript という言語が持つ優れた拡張性は、汚染とのトレードオフなのです。


uupaa.js - Glossary

もし、プロトタイプ汚染があるならばhasOwnPropertyを使うか、iframeを使ったきれいなオブジェクトを持ってくるなどの工夫が必要となる。

名前:  非公開コメント   

  • TB-URL  http://efcl.info/adiary/054/tb/