【解決済】JSキレイに書けないか質問

hkaru
記事: 29
登録日時: 2021年3月21日(日) 13:37

【解決済】JSキレイに書けないか質問

投稿記事by hkaru » 2021年6月15日(火) 20:09

もはやツクールほぼ関係なくてアレなのですが。

自作のスクリプトなのですが、この一行もっと美しく書けないでしょうか?

コード: 全て選択

var x = $gameActors.actor(1).equips()[0]==null ? 1 : $gameActors.actor(1).equips()[0].note

$gameActors.actor(1).equips()[0]
を二回書いているのが気持ち悪くて、だけどこれだけのために変数作るのもなぁって思ってます・・・

ささいな問題なんですが、気になってしまうと落ち着かない性分なんです。
助言いただけると嬉しいです。


追記:スクリプトの全文です。DBから値を取得たりして、計算結果を変数に入れています。

コード: 全て選択

var multi = $gameActors.actor(1).equips()[0]==null ? 1 : $gameActors.actor(1).equips()[0].note
var damage = $gameVariables.value(1) * $dataEnemies[1].note * multi + Math.floor(Math.random() * 6);
damage = damage<=1 ? 1 : damage;
$gameVariables.setValue(2, damage);
最後に編集したユーザー hkaru on 2021年6月17日(木) 12:26 [ 編集 1 回目 ]

奏ねこま
記事: 702
登録日時: 2016年1月20日(水) 20:04

Re: JSキレイに書けないか質問

投稿記事by 奏ねこま » 2021年6月15日(火) 20:45

このケースの場合は素直に変数に一度入れたほうが良いと思いますが。
私も何かと短く書きたがりなので案を出してみます。

コード: 全て選択

var x = (e => e ? e.note : 1)($gameActors.actor(1).equips()[0]);

コード: 全て選択

var x = ($gameActors.actor(1).equips()[0] || { note: 1}).note;

果たしてこれを「キレイなJS」と言えるかどうか。
1つ目のほうは変数に入れるのとやってることは同じですね。
hkaru
記事: 29
登録日時: 2021年3月21日(日) 13:37

Re: JSキレイに書けないか質問

投稿記事by hkaru » 2021年6月15日(火) 21:29

奏ねこま さんが書きました:このケースの場合は素直に変数に一度入れたほうが良いと思いますが。
私も何かと短く書きたがりなので案を出してみます。

コード: 全て選択

var x = (e => e ? e.note : 1)($gameActors.actor(1).equips()[0]);

コード: 全て選択

var x = ($gameActors.actor(1).equips()[0] || { note: 1}).note;

果たしてこれを「キレイなJS」と言えるかどうか。
1つ目のほうは変数に入れるのとやってることは同じですね。


回答ありがとうございます!

う、うわあぁぁぁ▂▅▇█▓▒('ω';)▒▓█▇▅▂
どっちも知らない構文でした・・・
というか条件分岐ifとswitchと参考演算子しかしらない・・・

上はアロー関数?と参考演算子の組み合わせでしょうか?
下のは何が何だか・・・

お手数おかけしますが、後学のために構文を説明しているページのリンクとかいただけないでしょうか?
調べるキーワードすらわからない・・・

JSちょっとわかってきたつもりでしたが、まだまだ勉強頑張らなければ・・・
アバター
WTR
記事: 558
登録日時: 2015年12月22日(火) 19:14

Re: JSキレイに書けないか質問

投稿記事by WTR » 2021年6月15日(火) 22:00

質問されてないところですが
ツクールには Math.randomInt() なる便利関数がいますね。
以下は等価です。

コード: 全て選択

Math.floor(Math.random() * 6);
Math.randomInt(6);


damage のリミット処理…

コード: 全て選択

//damage = damage<=1 ? 1 : damage;
//$gameVariables.setValue(2, damage);

$gameVariables.setValue(2, Math.max(1, damage));


とかでも?

奏ねこまさんのは…私も??でした 奥が深いなぁ
Twitter、はじめました。
https://twitter.com/wtr_in_reverie/
hkaru
記事: 29
登録日時: 2021年3月21日(日) 13:37

Re: JSキレイに書けないか質問

投稿記事by hkaru » 2021年6月15日(火) 22:17

WTR さんが書きました:質問されてないところですが
ツクールには Math.randomInt() なる便利関数がいますね。
以下は等価です。

コード: 全て選択

Math.floor(Math.random() * 6);
Math.randomInt(6);


damage のリミット処理…

コード: 全て選択

//damage = damage<=1 ? 1 : damage;
//$gameVariables.setValue(2, damage);

$gameVariables.setValue(2, Math.max(1, damage));


とかでも?

奏ねこまさんのは…私も??でした 奥が深いなぁ


WTR様、回答ありがとうございます!
むむむ、Math.randomInt()は初めて知りました。便利ですね・・・

コード: 全て選択

$gameVariables.setValue(2, Math.max(1, damage));

上記も「なるほど!」って感じで参考になります。
こうした小ネタ?は一度見ると確実に次に活かせるので、ありがたいです!
アバター
WTR
記事: 558
登録日時: 2015年12月22日(火) 19:14

Re: JSキレイに書けないか質問

投稿記事by WTR » 2021年6月15日(火) 22:43

パラパラとすみませんが…

最近どこか質問スレッドで似たようなのを書いた記憶があったので見直してみたら

コード: 全て選択

const actor = $gameActors.actor(1);
const multi = actor && actor.eqips()[0] ? actor.eqips()[0].note : 1;

みたいな書き方してました。(1行じゃねーじゃねーか

$gameActors.actor(1) が null だと equips() を呼んだ時点でエラーになるので
うるさいくらい null チェックして…

actor1がいないことはないんだろうと思いますが actorId も変数になる場合は気にした方がいいのかなぁと

追記
って書いたものの actor がいないのに multi が返ってきても意味ないから
潔くエラーで死ぬほうがわかりやすいのかもしれない
Twitter、はじめました。
https://twitter.com/wtr_in_reverie/
アバター
Plasma Dark
記事: 669
登録日時: 2020年2月08日(土) 02:29
連絡を取る:

Re: JSキレイに書けないか質問

投稿記事by Plasma Dark » 2021年6月15日(火) 23:13

自作のスクリプトなのですが、この一行もっと美しく書けないでしょうか?


この質問だといろんな尺度の美しいコードが集まりそうで、ちょっとワクワクしますね。

ねこまさんのようにワンラインでスッキリさせることにこだわる人もいれば、3行以上になるようならプラグインを書こうと言う人もいます。私はどちらかと言えば後者です。

ところで、コードをキレイに書くことの目的ははっきりしているでしょうか。

きれいなコードそのものを目的にしてしまう人もいますが、たいていの場合、目的は明日(あるいは1週間後、1ヶ月後、もしかしたら1年後)の自分が迷わず読めるコードにすることです。
そして、それにはだいぶ書き手の好みが反映されます。
私は今回のような例であれば、コードの横幅を考えて、変数を作ってしまうことが多いですね。

目下気になるのは
- .note に直接数値を入力したままで良いのか(他のmetaタグを使いたくならないか?)
- 敵の情報はDBから引いたもので良いのか(ステートなどで被ダメージ倍率が変化したりしないか?)
辺りですが、仕様検討中だったらすみません。気にしないでください。
chro
記事: 86
登録日時: 2021年2月14日(日) 11:26

Re: JSキレイに書けないか質問

投稿記事by chro » 2021年6月16日(水) 00:15

計算式は配列型で渡して短くかけます。
配列メソッドのreduceはいろんな使い方が出来ます。

コード: 全て選択

[1,2,3,4].reduce((acc, cur) => acc * cur, 1); //24

データベースのメモは文字列になるため、数値型への暗黙の型変換が行われています。
それをふまえて、配列を作成→掛け算→足し算→代入の流れにも出来ます。

コード: 全て選択

var multis = [
    (e => e ? e.note : 1)($gameActors.actor(1).equips()[0]),
    $gameVariables.value(1),
    $dataEnemies[1].note,
]
var damage = multis.reduce((acc, cur) => acc * (isNaN(cur) ? 1: Number(cur)), 1);
damage += Math.floor(Math.random() * 5);
$gameVariables.setValue(2, Math.max(1, damage));


オブジェクトのプロパティへは、ES2020で対応した書き方もあります。
https://developer.mozilla.org/ja/docs/W ... l_chaining

コード: 全て選択

$gameActors.actor(1).equips()[0]?.note

ただ、MZ以降かバージョンアップ出来ない古いモバイル端末では使用出来ません。

・調べるときに

暗黙の型変換
https://jsprimer.net/basic/implicit-coercion/

IIFE (即時実行関数式)
https://developer.mozilla.org/ja/docs/Glossary/IIFE

コード: 全て選択

const func = n => n + 1;

var num = func(1); //2
var num = (n => n + 1)(1); //2


演算子の優先順位
https://developer.mozilla.org/ja/docs/W ... Precedence
グループ化 ()の優先度は高い

論理積 (&&)
https://developer.mozilla.org/ja/docs/W ... ogical_AND
論理和 (||) 
https://developer.mozilla.org/ja/docs/W ... Logical_OR

Falsy (偽値)
https://developer.mozilla.org/ja/docs/Glossary/Falsy

コード: 全て選択

var obj = null;
var value = obj || {id:2}

value.id// 2
(obj || {id:2}).id //2
奏ねこま
記事: 702
登録日時: 2016年1月20日(水) 20:04

Re: JSキレイに書けないか質問

投稿記事by 奏ねこま » 2021年6月16日(水) 03:47

hkaru さんが書きました:お手数おかけしますが、後学のために構文を説明しているページのリンクとかいただけないでしょうか?
調べるキーワードすらわからない・・・

リンクは他の方が貼られたので回答することがなくなってしまいましたが、ざっくり説明だけでも。

1つ目はおっしゃるとおりアロー関数を使い三項演算子で値を返しているだけです。
アロー関数を即時関数として実行しています。

2つ目は論理和( || )の特性を利用した書き方です。
装備の有無によって論理和の左側を使うか右側を使うかが変わります。

装備があるとき: ($gameActors.actor(1).equips()[0]).note
装備がないとき: ({ note: 1 }).note

https://developer.mozilla.org/ja/docs/W ... Logical_OR
ここの「解説」「短絡評価」「例」を一通り読んでみてください。
hkaru
記事: 29
登録日時: 2021年3月21日(日) 13:37

Re: JSキレイに書けないか質問

投稿記事by hkaru » 2021年6月17日(木) 11:01

WTR さんが書きました:$gameActors.actor(1) が null だと equips() を呼んだ時点でエラーになるので
うるさいくらい null チェックして…

actor1がいないことはないんだろうと思いますが actorId も変数になる場合は気にした方がいいのかなぁと


WTR様、追記ありがとうございます。
参考になります。

今回はパーティは主人公オンリーの構想で組んでいるので、
$gameActors.actor(xx)のnullチェックとかは全く考えてなかったです(笑)

しかし、今後アクターを指定するような構想を組む場合には必要な情報だと思うので、記憶の片隅に置いておきます!
設計段階でそういうことに気づけばいいのですが、まだまだそのレベルには達せないですね・・・
精進します。

“MZ:質問” へ戻る