普段、Rubyを使い慣れているのでJavaScriptで配列やハッシュ、文字列等を操作するときに、「RubyでいうあのメソッドはJavaScriptにあるのかな？」と探す
or 実装するのが面倒です。

というわけでベーシックなオブジェクトをRubyっぽく操作できるJSライブラリがあれば教えてください。
CC BY-SA 3.0
2014-11-24T19:40:02.863
179
2014-12-16T02:27:44.580
85
question
javascript ruby
RubyっぽいAPIを提供してくれるJavaScriptのライブラリはありませんか？
Opalという、RubyコードをJavascriptに変換するサイト/ライブラリがあります。

<http://opalrb.org>

主要なRuby関数はライブラリになっていますので、こちらで変換して確認できるかと思います。
CC BY-SA 3.0
2014-11-25T01:23:22.830
180
2014-11-25T01:23:22.830
63
179
answer
[RubyJS](http://rubyjs.org/) という Ruby の API を模した JS ライブラリがあります。

以下のように `R` で包まなければいけないようです。

```

    R(1.2345).round(2) + 1
    // => 2.23
    
```

参考：<http://rubyjs.org/blog/2012/12/rubyjs-the-post-launch-launch-post/>
CC BY-SA 3.0
2014-12-02T01:08:29.023
211
2014-12-02T01:08:29.023
206
179
answer
RubyっぽいAPIがmodule
Enumerableのことを指しているなら[Underscore](http://underscorejs.org/)や、その[文字列拡張ライブラリ](https://github.com/epeli/underscore.string)がメジャーだと思います。functional
programming library for javascriptで検索すると上位に表示されるので。

```

    var stooges = [{name: 'curly', age: 25}, {name: 'moe', age: 21}, {name: 'larry', age: 23}];
    var youngest = _.chain(stooges)
      .sortBy(function(stooge){ return stooge.age; })
      .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
      .first()
      .value();
    => "moe is 21"
    
    _.mixin(_.str.exports()); // underscore と統合
    _('  capitalize dash-CamelCase_underscore trim  ').humanize()
    => 'Capitalize dash camel case underscore trim'
    ['foo20', 'foo5'].sort(_.naturalCmp)
    => [ 'foo5', 'foo20' ]
    
```

[fn.js](http://eliperelman.com/fn.js/)はカリー化もできます。
CC BY-SA 3.0
2014-12-02T14:54:06.587
269
2014-12-02T14:54:06.587
699
179
answer
Tetsuwo OISHIさんも書かれているように、RubyJSというライブラリがあります。
現在のバージョンは0.8.0-beta1という新しいものです。まだ知名度は低いかもしれませんが、Rubyライクなコーディングが好きな方にはよいかもしれません。

**RubyJS** <http://rubyjs.org/>

ドキュメントによると2つの使い方があるようです。

>   * RubyJS (Lite) - Functional
>   * RubyJS Classic - Object Oriented
>

先ずRubyJS (Lite)のほうは、Underscore.jsに似た関数スタイルで実装されているようです。

```

      String 関連の関数は、グローバルオブジェクトの　'_s' に、
      Array 関連の関数は、グローバルオブジェクトの　'_a' に、
      Time 関連の関数は、グローバルオブジェクトの　'_t' に、...
    
```

という具合です。

一方、RubyJS Classic
の方は、Lite版の機能を'`R`'という名前のラッパーオブジェクトを使って実装しているようです。こちらの関数は、戻り値としてラッパーオブジェクト自身を返すようになっていて、メソッドチェーンを組むことができます。

```

      R("foo");   // => {R.String: "foo"}
      R("foo").capitalize(); // => {R.String: "Foo"}
      R("foo").capitalize().ljust(7, '-'); // => {R.String: "--Foo--"}
    
```

* * *

# JavaScript / Underscore.js / RubyJS の比較

RubyJSの[ドキュメントページ](http://rubyjs.org/reloaded/#overview-
benefitsForJsDevelopers)に、純粋なJSとUnderscore.jsと書き方を比較するコードが載っています。その中から2つの部分を選んで以下に補足します。

## 比較1. 配列中の文字列を数値に変換

>
```

>      // JS
>      ['10', '10', '10'].map(parseInt)     // => [10, NaN, 2]
>      // underscore
>      _.map(['10', '10', '10'], parseInt)  // => [10, NaN, 2]
>      // RubyJS
>      _a.map(['10', '10', '10'], parseInt) // => [10, 10, 10]
>  
```

このコードが言わんとしていることは、「JSやunderscoreでは配列中の文字列をまとめてparseIntできないけど、RubyJSなら簡単です。」ということだと思います。確かにそうですが、このままだとJSとunderscoreが言われっ放しで少しかわいそうな気もするので以下に補足してみます。

**純粋なJavascriptの場合**

Javascriptの`Array.map()` を使ってparseIntするときに、以下のように書くと予想外の結果になります。

```

     ['10', '10', '10'].map(parseInt);     // => [10, NaN, 2]
    
```

これは、`parseInt()`関数の引数が1つではないことに起因しています。

>
```

>     var intValue = parseInt(string[, radix]);　//第2引数は基数（10進の場合は10）
>  
```

>
> [Mozilla Developper
> Network](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/parseInt)より引用

対処方法はいくつかありますが、そのひとつは`bind()`関数を使うものです。`bind()`の第2引数に基数10（10進数）を指定することができます。

```

     ['10', '10', '10'].map(parseInt.bind(null, 10));// => [10, 10, 10]
    
```

あるいはもっとシンプルに、`parseInt()`の代わりに`Number()`を使う方法もあります。JavaScriptの`Number()`はラッパーオブジェクトですが、`new`演算子をつけないで呼び出すと型変換関数として動作します。

```

     ['10', '10', '10'].map(Number); // => [10, 10, 10]
    
```

これならばシンプルですし、RubyJSと比べても見劣りしないと思います。

**Underscore.jsの場合**

Underscoreでは、デフォルトで`_`（アンダースコア）という名前のグローバルオブジェクトが定義されています。その`_`に実装されているmap関数を使って、配列にコールバック関数を関連付けます。上で述べたJSの場合と同様に、以下のどちらかの方法で数値化できます。

```

     _.map(['10', '10', '10'],parseInt.bind(null, 10));　 // => [10, 10, 10]
     _.map(['10', '10', '10'],Number);　 // => [10, 10, 10]
    
```

**RubyJSの場合**

RubyJSでは、`_a`という名前のグローバルオブジェクトに配列関連のメソッドが定義されています。 以下のどちらの書き方もできます。

```

     _a.map(['10', '10', '10'], parseInt); // => [10, 10, 10]
     _a.map(['10', '10', '10'], Number); // => [10, 10, 10]
    
```

確かにシンプルにコーディングできます。

* * *

## 比較2. 配列のソート

もうひとつの比較を見てみます。ここでは、配列を`sort()`するコードが載っています。

>
```

>     // JS
>     [1, 8, 15].sort()     // => [1, 15, 8]
>     // underscore
>     _.sortBy([1, 8, 15])  // => [1, 15, 8]
>     // RubyJS
>     _a.sort([1, 8, 15])   // => [1, 8, 15]
>  
```

このコードが言わんとしていることは、「JSやunderscoreでは配列中の文字列を単純にソートきないけど、RubyJSなら簡単だよ」ということだと思います。更に解りやすくするために、数値を書き換えて以下のようにして考えます。

```

     // JS
     [33,4,1111,222].sort()     // =>  [1111,222,33,4]
     // underscore
     _.sortBy([33,4,1111,222])  // => [1111,222,33,4]
     // RubyJS
     _a.sort([33,4,1111,222])   // =>　[4, 33, 222, 1111]
    
```

**純粋なJavascriptの場合**

Javascriptの`Array.sort()` を使って以下のようにすると、アルファベット順にソートされた結果が返ります。

```

     [33,4,1111,222].sort();     // => [1111,222,33,4]
    
```

アルファベットではなく数値として比較したい場合には、以下のように書けます。

```

     [33,4,1111,222].sort(function(a,b){ return a - b;})); // => [4, 33, 222, 1111]
    
```

**Underscore.jsの場合**

Underscoreでは、`sortBy()`を使って以下のようにできます。

```

     _.sortBy([33,4,1111,222], function(num){ return num; });// => [4, 33, 222, 1111]
    
```

**RubyJSの場合**

```

     _a.sort([33,4,1111,222])// => [4, 33, 222, 1111]
    
```

確かにシンプルです。

以上です。Rubyライクなコーディングが好きな方にはよいかもしれません。

上述のコードを[JSFiddle](http://jsfiddle.net/naokiota/24ceLxv7/1/)に置きました。
CC BY-SA 3.0
2014-12-05T08:18:56.913
366
2014-12-11T05:19:59.957
2014-12-11T05:19:59.957
47
47
179
answer
プロトタイプ拡張を許すならRuby風にネイティブオブジェクトを拡張するsugar.jsが便利でした。作者がrubyistなのでだいたいのrubyのメソッドは定義されています。詳しくは以下のドキュメントにて。

[Sugar: A Javascript library for working with native
objects.](http://sugarjs.com/ "Sugar: A Javascript library for working with
native objects.")

プロトタイプ拡張を許さない環境なら underscore.js や lodash.js を使うでしょう。
CC BY-SA 3.0
2014-12-16T02:27:44.580
1634
2014-12-16T02:27:44.580
2674
179
answer