Rubyist が Javascripter になり始めてやらかしたこと (備忘録) 

## 概要 ##

Electronアプリ開発に祭して、Javascriptを本格的に書くようになってから半年経ちました。   
Railsアプリを書くことはあっても、view側のJSを本格的に書くことはありませんでした。   
(その他もLambdaで少々...といったくらい)   
   
Rubyistならではのハマり所って実は結構あるのでは？と思い、備忘録的に残しておくことにします。   
※ どちらの言語がいいという話ではありません。

先に言語仕様を確認しておけば良いという話ではあります。   
違いが面白かったりまどろっこしかったり、楽しんだ記録になります。


## 言語歴 ##

* Ruby : 9年目
* Javascript : 1年目 (半年)
* その他
    * Python 2.x (数ヶ月)
    * Erlang (数ヶ月)
    * C (大学で少々レベル)

## 以下、多分一度はやったやつ ##

### 最初にやるやつ ###

* `==` で比較する
* `;` を書かない
* 関数定義の引数部分に `()` を付けない, `{}` 閉じ忘れる
* 関数の呼び出しに `()` を付けない
* 関数の引数の数が幾つでも良い(0個でもいい)
* const, let を書かない (& varのスコープでハマる)
* ついついスネークケースで名前付け

### Return を書かない ###

最後の評価値が返ることが身に染み付いてしまっている。   
`undefined` になっていることに気づくのはテストを書いたときか、動かしてからか...。   

```rb
def hoge
  "hogehoge"
end

hoge  #=> "hogehoge"
```

```js
function hoge() {
  "hogehoge";
};

hoge();  //=> undefined
```


### 可変長引数 ###

`*` がない！とならないように。

```rb
def func(*args)
  p args  #=> ["a", "b", "c"]
end
func('a', 'b', 'c')
```

```js
function func(...args) {
  console.log(args)
}
func('a', 'b', 'c')  //=> [ 'a', 'b', 'c' ]
```


### callbackがやたら気持ち悪く感じる ###

常時 `lambda` を渡しているような感じがする。   
rubyの感覚的にはこんな感じ。まどろっこしく感じる。

```rb
class Array
  def forEach(func)
    self.each do |n|
      func.call(n)
    end
  end
end

[1, 2, 3].forEach(lambda {|n|
  puts n
})
```

```js
[1, 2, 3].forEach((n) => {
  console.log(n);
});
```


### this でやらかす ###

例は `forEach` 。jsの `this` は要注意。

```rb
class Foo
  def three; 3; end

  def bar
    [1, 2, 3].each do |n|
      puts n * self.three  #=> 3, 6, 9
    end
  end
end

Foo.new.bar
```

```js
class Foo {
  three() { return 3; };

  bar() {
    /*
    [1, 2, 3].forEach(function(n) {
      console.log(n * this.three());  //=> TypeError: Cannot read property 'three' of undefined
    });
    */

    // 関数式にthisを指定する
    [1, 2, 3].forEach(function(n) {
      console.log(n * this.three());  //=> 3, 6, 9
    }, this);

    // アロー関数を使う
    [1, 2, 3].forEach(n => {
      console.log(n * this.three());  //=> 3, 6, 9
    });
  }
}

(new Foo).bar()
```


### sleepが書きたいんだ! ###

ただし `Promise` にして待たないと意味はないので2度やらかす。

```rb
sleep(3)
```

```js
setTimeout(() => {}, 3000);
```


### 非同期なにそれ ###

その `Promise` の話。   
非同期関数の戻り値が `Promise` であることを忘れる or 知らない。   
(setTimeoutをどう待てばいいんだ？でみんな一度は手を止めるのでは...?)

```js
class Baz {
  asyncMyFunc() {
    return new Promise(resolve => {
      setTimeout(() => { resolve("qux");  }, 3000);
    });
  };

  async qux() {
    let val = this.asyncMyFunc();
    console.log(val);  // => Promise { <pending> }

    let val2 = await this.asyncMyFunc();
    console.log(val2);  // => "qux"
  };
};

(new Baz).qux();
```


### await を知らないために callback 地獄へ ###

これが噂に聞く...という状態だった。

```js
foo().then(result => {
  bar().then(result => {
    baz().then(result => {
      // ...
    });
  });
});
```

```js
let result
result = await foo()
result = await bar()
result = await baz()
```


### async と await の書き方に慣れない ###

`await` は`async` function のなかに書ける。   
`async` function を await するように思ってしまうがそうじゃない。

```js
async function piyo() {
  await asyncFunc()
}
piyo()
```


### モンキーパッチ書きたいんだ! ###

ちょっとした時に。   
先ほどの `Foo#three()` を書き換える例。

```rb
Foo.new.three  #=> 3
class Foo
  def three; "3"; end
end
Foo.new.three  #=> "3"

```

```js
(new Foo).three();  //=> 3
Foo.prototype.three = function() { return "3" };
(new Foo).three();  //=> "3"
```


### rspec -> mocha 書きたいんだ! ###

* `subject` , `is_expected` 等々はなさそう

```js
const expect = require('chai').expect
describe('Foo', () => {
  beforeEach(() => {
    // ...
  })
  let foo = new Foo

  describe('#hoge()', () => {
    it ('return "hogehoge"', () => {
      expect(foo.hoge()).to.equal("hogehoge");
    });
  });

  // 非同期関数のテスト
  describe('#fuga()', () => {
    it ('return "hogehoge"', async () => {
      expect(await foo.fuga()).to.equal("fugafuga");
    });
  });

  // shared_example 的に使える
  function piyo() {
    it ('return "piyopiyo"', () => {
      expect(Foo.piyo()).to.equal("piyopiyo");
    });
  };

  describe('#piyo()', piyo);

  context('when ...', () => {
    // ...
  });
});
```

```
$ ./node_modules/.bin/mocha 


  Foo
    #hoge()
      ✓ return "hogehoge"
    #fuga()
      ✓ return "hogehoge" (1006ms)
    #piyo()
      ✓ return "piyopiyo"


  3 passing (1s)


```

その他、今後も思い出したり出会い次第追記予定です。