概要
Electronアプリ開発に祭して、Javascriptを本格的に書くようになってから半年経ちました。
Railsアプリを書くことはあっても、view側のJSを本格的に書くことはありませんでした。
(その他もLambdaで少々...といったくらい)
Rubyistならではのハマり所って実は結構あるのでは?と思い、備忘録的に残しておくことにします。
※ どちらの言語がいいという話ではありません。
先に言語仕様を確認しておけば良いという話ではあります。
違いが面白かったりまどろっこしかったり、楽しんだ記録になります。
言語歴
- Ruby : 9年目
- Javascript : 1年目 (半年)
- その他
- Python 2.x (数ヶ月)
- Erlang (数ヶ月)
- C (大学で少々レベル)
以下、多分一度はやったやつ
最初にやるやつ
-
==
で比較する -
;
を書かない - 関数定義の引数部分に
()
を付けない,{}
閉じ忘れる - 関数の呼び出しに
()
を付けない - 関数の引数の数が幾つでも良い(0個でもいい)
- const, let を書かない (& varのスコープでハマる)
- ついついスネークケースで名前付け
Return を書かない
最後の評価値が返ることが身に染み付いてしまっている。
undefined
になっていることに気づくのはテストを書いたときか、動かしてからか...。
def hoge
"hogehoge"
end
hoge #=> "hogehoge"
function hoge() {
"hogehoge";
};
hoge(); //=> undefined
可変長引数
*
がない!とならないように。
def func(*args)
p args #=> ["a", "b", "c"]
end
func('a', 'b', 'c')
function func(...args) {
console.log(args)
}
func('a', 'b', 'c') //=> [ 'a', 'b', 'c' ]
callbackがやたら気持ち悪く感じる
常時 lambda
を渡しているような感じがする。
rubyの感覚的にはこんな感じ。まどろっこしく感じる。
class Array
def forEach(func)
self.each do |n|
func.call(n)
end
end
end
[1, 2, 3].forEach(lambda {|n|
puts n
})
[1, 2, 3].forEach((n) => {
console.log(n);
});
this でやらかす
例は forEach
。jsの this
は要注意。
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
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度やらかす。
sleep(3)
setTimeout(() => {}, 3000);
非同期なにそれ
その Promise
の話。
非同期関数の戻り値が Promise
であることを忘れる or 知らない。
(setTimeoutをどう待てばいいんだ?でみんな一度は手を止めるのでは...?)
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 地獄へ
これが噂に聞く...という状態だった。
foo().then(result => {
bar().then(result => {
baz().then(result => {
// ...
});
});
});
let result
result = await foo()
result = await bar()
result = await baz()
async と await の書き方に慣れない
await
はasync
function のなかに書ける。
async
function を await するように思ってしまうがそうじゃない。
async function piyo() {
await asyncFunc()
}
piyo()
モンキーパッチ書きたいんだ!
ちょっとした時に。
先ほどの Foo#three()
を書き換える例。
Foo.new.three #=> 3
class Foo
def three; "3"; end
end
Foo.new.three #=> "3"
(new Foo).three(); //=> 3
Foo.prototype.three = function() { return "3" };
(new Foo).three(); //=> "3"
rspec -> mocha 書きたいんだ!
-
subject
,is_expected
等々はなさそう
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)
その他、今後も思い出したり出会い次第追記予定です。