質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

4回答

5629閲覧

jQueryの無名関数の入れ子って問題ないですか?

mametaro3

総合スコア13

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2018/12/28 08:21

編集2018/12/28 08:25

こんな書き方って問題ないですか?

js

1; 2(function ($) { 3 $(function () { 4 $(function () { 5 無名関数1 6 }); 7 $(function () { 8 無名関数2 9 }); 10 $(function () { 11 無名関数3 12 }); 13 14 $(window).on('load resize', function () { 15 ロード・リサイズ処理1 16 }); 17 $(window).on('load resize', function () { 18 ロード・リサイズ処理2 19 }); 20 21 . 22 . 23 . 24 25 }); 26 27})(jQuery); 28

jQueryでカプセル化するのは問題ないと思うのですが、無名関数に無名関数を入れ子したり、無名関数を機能ごとに分けたりすることって問題ないのでしょうか?

無名関数を小分けにしすぎると、パフォーマンスに障るのかなと気になりました。

気になる点

こういう場合は

js

1; 2(function ($) { 3 $(function () { 4 // アンカーリンクを〜〜する 5 無名関数1 6 // #hoge〜〜する 7 無名関数2 8 // △△を○○する 9 無名関数3 10 }); 11 12 $(window).on('load resize', function () { 13     // リサイズしたとに画面幅を取得する 14 ロード・リサイズ処理1 15     // リサイズしたときに〜〜する 16 ロード・リサイズ処理2 17 }); 18})(jQuery); 19

と、コメントかなにかで機能を区切るように書き換えるか、

js

1; 2(function ($) { 3 $(function () { 4 関数1(); 5 関数2(); 6 関数3(); 7 }); 8 9 $(window).on('load resize', function () { 10 ロード・リサイズ処理1(); 11 ロード・リサイズ処理2(); 12 }); 13 14 . 15 . 16 . 17 18 (関数の記述) 19 }); 20 21})(jQuery); 22

上記のように関数を作ってあげたほうがいいのではないかと思うのですが

これらにパフォーマンスや可読性の違いはでますか?
またこういう無名関数の入れ子の問題はjQueryだけではなく、JSやその他のプログラミング言語でも同じことが言えるのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

これらにパフォーマンスや可読性の違いはでますか?

JavaScriptの関数実行はそれなりに性能が良いのでパフォーマンス的なダメージは殆どありません。
ループ文なんかで数万個単位の関数を機械的に生成してしまう等の状態になれば話は別ですが、
人間が手作業で作る数十個の関数がパフォーマンス上の決定的差になる事はありえません。

可読性は当然落ちます。
関数を作る度に、開きと閉じでビジネスロジックを満たす為に何の寄与のしない行が2行ずつ加算されますので、
程度問題とはいえJSのコードは出来るだけ行数を絞った方が分かりやすいといえます。

無名関数の入れ子

違いますぅ!無名関数の入れ子じゃないですぅ!!

(function ($) {})(jQuery);はまごうことなき無名関数です。
$(function(){});はjQuery関数にコールバック関数を引数に実行しただけで、
その本質はaddEventListenerへのイベント登録です。

JavaScriptの関数は他の値と同じく、
「変数に代入可能」「関数の引数に格納可能」「関数の戻り値に設定可能」という特徴(第一級オブジェクト)があり、
これを利用して「イベント登録」という儀式を行う言語です。

登録するイベントの候補にはブラウザが用意したページのロードが完了したとき、マウスがクリックされたとき、要素の上にマウスカーソルが乗ったとき……とまぁ無数に存在しまして、
その登録時に「Aのイベント条件を満たしたとき」に、後続の処理をTODOリスト的に関数として包んだものをセットにするのです。

要するに一見無駄に見えるこの関数の入れ子は見てくれじゃなくてちゃんと意味があるんです。
まぁ、グローバル領域にjQueryという変数がぷかぷか浮かんでて、
無名関数で束縛しなければならないというのはちょっとアレな話ですけどね。

jQueryでカプセル化するのは問題ないと思うのですが、無名関数に無名関数を入れ子したり、無名関数を機能ごとに分けたりすることって問題ないのでしょうか?

上記を踏まえて質問文の冒頭を見返しましょう。
貴方が考える新しいやり方は、「イベントを細かく定義して」疎結合なWebアプリを作りたいという試みといったところでしょう。
私もかなり悩んだ末にこのやり方を思いついた経緯がありまして、こうして見返しても中々筋が良い方法だと思います。

……で、ここからが本題ですが、どうしてこのやり方を編み出したのでしょうか?
恐らく大規模なWebアプリケーション開発をしている最中、必要に迫られてではないですか?
だとすれば、jQueryや素のJavaScriptによるイベント駆動開発の辛みが一気に吹き出してきて地獄になります。

そして疎結合にしている部分の変数共有が必要になり、次第にジリ貧になり、
技術的負債が溜まってプロジェクトが一気に遅延するでしょう。
この辺までが既定路線です。

私がこの手法を考えついたのは2010年頃の話ですが、今は既にもっと良い方法が認知され、普及しています。
JSフレームワークであるReact、Vue.js、Angular等にシフトすることをオススメします。
その手法を突き詰めて頑張るならさっさとJSフレームワークに移行しろ!間に合わなくなっても知らんぞー!!という感じです。

またNode.jsアプリのWebpackやBrowserifyで勉強してみてください。
関数の切り分けというところでかなり楽になるはずです。

投稿2018/12/28 09:28

編集2018/12/28 09:58
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mametaro3

2019/01/07 04:33

> `$(function(){});`はjQuery関数にコールバック関数を引数に実行しただけで、 その本質はaddEventListenerへのイベント登録です。 ↑なるほど!無名関数と呼んでしまいました.. ちなみにこれは即時関数とは呼べるのでしょうか? 通常はイベント登録と呼べばよいのでしょうか..? > ……で、ここからが本題ですが、どうしてこのやり方を編み出したのでしょうか? ↑関数を細かく登録して..ってやりかたのことですよね! C#エンジニアの方が、angularとtypescript+webpackで開発しているwebアプリのソースを触らせていただける機会がありまして、関数のカプセル化というのを見て、こちらのほうが見やすいのではと思い至りました! とても参考になりました! ありがとうございます。
miyabi-sun

2019/01/07 05:19 編集

`function name() {}`という形で文章としておかず、 `var fn = function () {}`、`$(function(){})`等と書いたら無名関数です。 確かに無名関数ではあるのですが、 イベント登録の入れ子なので純粋な無名関数を使った即時実行関数の入れ子ではないという感じですね。 > 通常はイベント登録と呼べばよいのでしょうか..? jQueryの$(fn)をちゃんと読んでは居ないのですが、 本質的にはイベント登録の入れ子ですね。
mametaro3

2019/01/07 08:10

あぁ!なるほど.. 腑に落ちました。ご丁寧な回答、ありがとうございました!!
guest

0

文法上エラーが出なければ問題ないでしょうけど
パフォーマンスを気にするなら、あまりやる意味がないと思いますのでやめたほうがいいかと。

$(window).onについてもresize時はともかくload時をあえて切り分ける理由があるかは微妙です
(いちおうレンダリングを経てからの処理なのでしょうけど)よほどセンシティブな作りでなければ
DOMContentLoaded時でもさほど影響はないと思いますので、多重処理しないほうがよいかと。

投稿2018/12/28 08:40

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mametaro3

2019/01/07 04:37

ご回答ありがとうございます! そうですよね。省けるならシンプルなほうがいいですよね。 $(window).on('load resize', function () { ロード・リサイズ処理1 }); ↑のloadはいらないってことですか? load時とresize時に発火してほしくてこうなったのかと思ってましたが、 こちらはresizeのみで大丈夫ということでしょうか..?
guest

0

大丈夫だ、問題ない

こんな書き方って問題ないですか?

問題の有無は、人それぞれの判断基準でいくらでも変化します。

  • パフォーマンス
  • 美的感覚
  • 対応ブラウザ
  • 期待する動作

質問者が期待している要件を明らかにして、その要件に最もマッチするコードを探し出すのが「最適解」だと私は思います。

独断と偏見で要件を決めて書いたコード

  • $ は内容を表さない不適切な関数名です。jQuery を使いましょう。
  • 同じ関数を分割して何度も呼び出すのは無駄です。DRY 原則に従い、一つにまとめましょう。
  • グローバル名前空間を使用しない為に、即時関数は不要です。ブロックスコープを使いましょう。

HTML

1<script> 2{ 3 'use strict'; 4 5 const joinHandlers = function joinHandlers () { 6 const handleList = arguments; 7 8 return function handlers () { 9 for (let handle of handleList) { 10 handle.apply(this, arguments); 11 } 12 }; 13 }; 14 15 const fn1 = function fn1 () {}; 16 const fn2 = function fn1 () {}; 17 const fn3 = function fn1 () {}; 18 const loadResize1 = function loadResize1 () {}; 19 const loadResize2 = function loadResize2 () {}; 20 21 jQuery(joinHandlers(fn1, fn2, fn3)); 22 jQuery(this).on('load resize', joinHandlers(loadResize1, loadResize2)); 23} 24</script>

Re: mametaro3 さん

投稿2018/12/28 12:38

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mametaro3

2019/01/07 04:40

ご回答ありがとうございます! なるほど、こんな書き方もあるのですね。参考になりました。
guest

0

$(function () {}); は 「 DOMContentLoaded イベント発報時もしくはそれ以降であれば即実行」という挙動をします。そのため、複数書く必要は全くありません。

js

1$(function () { 2 $(function () {/*中身*/}); // これは特に意味が無い 3}); 4```5```js 6$(function () { 7 /*中身*/ 8});

投稿2018/12/28 09:31

kei344

総合スコア69407

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mametaro3

2019/01/07 04:20

ご回答ありがとうございます。なるほど、そうですよね! 参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問