青柳臣一 blog : .NET や C# がメインの blog

.NET や C# がメインの blog
投稿数 - 548, コメント - 259, トラックバック - 205

JavaScript で LINQ 風のことをやる

Script and LINQ? より

いやぁ、おもしろいです。「JavaScript で LINQ 風の書き方なんて簡単にできるんじゃね?」 という話が紹介されています。以下、理解したことを自分なりにまとめておきます。 

まず JSON を使えば ※1 Anonymous Type と Initializer みたいなことができます。
(※1 「JSON を使えば」 っていうのもなんか変な言い方ですね。「JSON で使っている記法を使えば」 と言ったらいいのかな?)

// JavaScript
var person = { Name: "Hoge Taro", Age: 20, Tel: "111-1111" };

これだけで C# の

// C#
class Person
{
    public string Name;
    public int Age;
    public string Tel;
}
Person person = new Person();
person.Name = "Hoge Taro";
person.Age = 20;
person.Tel = "111-1111";

とほとんど同じような意味になるわけです。
そして、配列だって

// JavaScript
var persons = [
    { Name: "Hoge Taro", Age: 20, Tel: "111-1111" },
    { Name: "Hoge Jiro", Age: 18, Tel: "222-2222" },
    { Name: "Hoge Saburo", Age: 15, Tel: "333-3333" }
];

と書けます。

さて、次に

// C#
var result = 
    from p in persons
    where p.Age <= 18
    select new {
        Name = p.Name,
        Age = p.Age
    };

といういかにも LINQ という書き方についてです。
さすがに標準の JavaScript でこういう書き方はできません。しかし、

// JavaScript
var result =
    persons.filter(function(p) { return p.Age <= 18; })
           .map(function(p) {
               return { Name: p.Name, Age: p.Age };
           });

と書けます。LINQ を Extension Method を呼び出す形で書いたときとよく似てますね。
JavaScript では配列は Array クラスですが、上記の filter とか map とかは Array クラスのメソッドです。どうやら Mozilla ではこういったメソッドがサポートされているようです。しかし、IE では 「サポートされていないメソッド」 となってエラーになってしまいます。

「んじゃあ、使えないじゃん」 となるんですが、もともと JavaScript では実行時にメソッドとかを足していってクラス (みたいなもの) を作るわけです。ならば、Array クラスに filter とか map とかを自分で足してやればいいわけですね。

というわけで、以下のコードは IE6 でちゃんと動きました。
ちなみに、以下の filter とか map とかは一から自分で書いたわけじゃありません。Script# に含まれている sscorlib.js から拝借したものです (ちょっとだけ変更してますが)。
いやぁ、JavaScript ってすごいですね。この記事を読んだときは感動しちゃいました。

<script>
Array.prototype.filter = function(filter_function)
{
    var result = [];
    for (var i = 0; i < this.length; ++i)
    {
        if (filter_function(this[i]))
        {
            result[result.length] = this[i];
        }
    }
    return result;
}

Array.prototype.map = function(map_function)
{
    var result = [];
    for (var i = 0; i < this.length; ++i)
    {
        result[result.length] = map_function(this[i]);
    }
    return result;
}

var persons = [
    { Name: "Hoge Taro", Age: 20, Tel: "111-1111" },
    { Name: "Hoge Jiro", Age: 18, Tel: "222-2222" },
    { Name: "Hoge Saburo", Age: 15, Tel: "333-3333" }
];

var result =
    persons.filter(function(p) { return p.Age <= 18; })
           .map(function(p) {
               return { Name: p.Name, Age: p.Age };
           });

for (var i = 0; i < result.length; ++i)
{
    alert(result[i].Name + "," + result[i].Age);
}
</script>

投稿日時 : 2006年12月26日 20:09

トラックバックは下記のURLにpingを送信してください。
TrackBack URL: http://www.divakk.co.jp/blog/aoyagi/services/trackbacks/7378.aspx

フィードバック

No comments posted yet.

コメントの投稿

タイトル  
名前  
URL
コメント   
Protected by Clearscreen.SharpHIPこの絵に表示されている文字列を入力してください (半角で4文字です):