回避すべきjQueryの落とし穴[クローズド]


210

私はjQueryでプロジェクトを始めています。

jQueryプロジェクトでどんな落とし穴/エラー/誤解/誤用/誤用がありましたか?


4
これは「建設的でない」ために閉じられるべきでありませんでした。いくつかの非常に役立つ回答が具体化し、この質問には現在220回スターが付けられています。カルマが十分にある場合は、投票して再開してください。
Roy Prins、2015年

私には、jQuery自体が落とし穴だと思われる
gromit190

回答:


189

パフォーマンスヒットに気付かず、セレクターをローカル変数に割り当てる代わりに、セレクターを使いすぎている。例えば:-

$('#button').click(function() {
    $('#label').method();
    $('#label').method2();
    $('#label').css('background-color', 'red');
});

のではなく:-

$('#button').click(function() {
    var $label = $('#label');
    $label.method();
    $label.method2();
    $label.css('background-color', 'red');
});

またはチェーンを使用するとさらに良い:-

$('#button').click(function() {
    $("#label").method().method2().css("background-color", "red"); 
});

コールスタックがどのように機能するかを理解したとき、私はこれが啓蒙的な瞬間だと思いました。

編集:コメントに提案を組み込みました。


16
YouTubeリンクの+1。私はたくさんのことを学びました。
Jason、

23
ローカル変数に物事を割り当てることは素晴らしいと思いますが、(あなたの例から)連鎖の力を忘れないでください:$( "#label")。method()。method2()。css( "background-color"、 "赤");
ランスマクニーニー2009

YouTubeビデオは素晴らしかった。このテーマに関する他のGoogleプレゼンテーションを見たことがありますが、それでもいくつかのことを学びました。ありがとう!
ガブリエルハーレー

リンクの+1もすばらしい!
Josh Stodola、

7
jQueryコンテキストで変数にドル記号を使用するのは、一種の規則です。だからあなたは書きたいかもしれませんvar $label = $('#label');
TimBüthe2010

90

コンテキストの使用方法を理解します。通常、jQueryセレクターはドキュメント全体を検索します。

// This will search whole doc for elements with class myClass
$('.myClass');

しかし、コンテキスト内で検索することにより、物事をスピードアップすることができます:

var ct = $('#myContainer');
// This will search for elements with class myClass within the myContainer child elements
$('.myClass', ct);

9
ああああ!まあ、それは修正された私のバグの約1,000,000です。+1
ジャムス2009

4
-それはあなたの最後の点が間違っているようだgroups.google.co.uk/group/jquery-dev/browse_thread/thread/...
ジェームズ・

1
JPを指摘していただきありがとうございます。さて、どうすればいいのでしょうか...答えを削除して、他の人が独り占めしてコードを何も変更しないようにする必要がありますか?
slolife 2009

いや、それはまだ最適化の点で良い点です。:)
ジェームズ

2
jQueryは、コンテキストがjQueryのインスタンスであるかどうかを確認するため、理由はありません[0]$('.myClass', ct);または、ctがjQueryのインスタンスであることがわかっている場合は、findを使用できますct.find(".myClass")
gradbot

62

次のように、裸のクラスセレクタを使用しないでください。

$('.button').click(function() { /* do something */ });

これはすべての要素を調べて、「ボタン」のクラスがあるかどうかを確認します。

代わりに、次のように手伝うことができます。

$('span.button').click(function() { /* do something */ });
$('#userform .button').click(function() { /* do something */ });

去年はレベッカ・マーフィーのブログでこれを学びました

更新 -この回答は2年以上前に出されたものであり、jQueryの現在のバージョンには正しくありません。コメントの1つには、これを証明するテストが含まれています。この回答の時点でのjQueryのバージョンを含むテストの更新バージョンもあります。


6
逆もまた真実だと感じました。おそらくこれは、getElementsByClassNameを実装していないブラウザーの場合ですが、それ以外の場合は、jQueryに実行する作業を追加するだけです。私はレベッカがいくつかのベンチマークを投稿するのをとても望んでいます:)
Alex Barrett

7
あなたはそれがしなければならない仕事の量を減らしています。靴下を部屋から出すように言うのではなく、誰かに靴下をドレッサーの引き出しから出すように言うようなものです。「見た目」の量を大幅に削減します。
卑劣2009

4
CSSを作成している場合(少なくとも要素タグを含む場合)は、その逆になります。code.google.com/speed/page-speed/docs/…を
kmiyashiro

7
@卑劣すべてが現実の正確な類似物を持っているわけではありません。たとえば、ブラウザがサポートしている場合に$('.b')使用できますdocument.getElementsByClassName('b')が、そうすると$('a.b')、クラスbと一致するすべての要素が取得され、2段階の操作でそれらがアンカーであることを確認します。後者は私にはもっと仕事のように聞こえます。実際のアナロジーについては、これを試してください:私の部屋ですべての靴下を見つけます。さて、私のドレッサーにないものを捨ててください。
アレックス

2
セレクターの誤解は、jqueryの古いバージョンでは、定義によりIDが一意であるため、$( 'div#foo')よりも$( '#foo')の方が高速であったという事実が原因であると思います。これは後のリリースで修正されたと思いますが、その推奨事項はIDにのみ適用され、他のタイプのセレクターには適用されませんでした
Alex Heyd

35

匿名関数を分割して、再利用できるようにしてください。

//Avoid
$('#div').click( function(){
   //do something
});

//Do do
function divClickFn (){
   //do something    
}

$('#div').click( divClickFn );

19
これは、同期(インライン)コードが名前付き関数に分割されるのとほぼ同じ程度に当てはまると思います。名前を付けられそうなコードのチャンクを手に入れたら、それを試してください。ただし、コードを関数の中にラップしているという理由だけで、コードを外に移動しないでください。匿名関数は正当な理由で存在します。
Dan Breslau、

4
実際、私は自分の関数に「名前」を付けるのが好きです。これは、コードをデバッグするときに非常に役立ちます。無名関数の無限のリストを表示する代わりに、適切に名前が付けられた関数が表示されます。
SolutionYogi

1
あなたの主張はよく理解されており、おそらく私自身もこれに数回つまずかれたことがあります。それでも、「大体同じ程度」でもうまくいきます。
Dan Breslau、

1
特に バインディングがループで発生している場合!
daniellmb 2009

名前付き関数は、デバッグ時にも非常に役立ちます。何もない8レベルのコールスタックを見るだけで、何も問題はありません(anonymous)。ここでは、この先端にもっと読むstackoverflow.com/questions/182630/jquery-tips-and-tricks/...

34
  • ドキュメントを乱用しないでください。
  • ドキュメントを初期化コードのみの準備をします。
  • 常にドキュメントの外で関数を抽出して、再利用できるようにします。

doc readyステートメント内の数百行のコードを見てきました。醜く、読みにくく、維持することが不可能です。


6
+1。一般に、私が目にしたjQueryコードのほとんどは、数百行の関数を使用しています。「jQuery開発者」がより小さな関数を使いたくない理由を知りません。
SolutionYogi

6
@SolutionYogiはJS初心者だけなので、
adamJLev

非常に長い関数をドキュメントに準備しないようにしてください。それは良いアドバイスです。ただし、ドキュメントの準備が整っていない包括的な関数から実行される多くの小さなコンポーネント関数を作成することは、必ずしもベストプラクティスとは限りません。包括的な関数がこれらのコードを使用する唯一の関数である場合は、読みにくい場合でも、すべてを1つの関数に配置することをお勧めします。関数の呼び出しには多くのオーバーヘッドがあり、1つのコンテキストでのみコードを使用している場合は回避する必要があります。
sage88 2013

34

サーバー$.ajaxへのAjaxリクエストに関数を使用している間は、completeイベントを使用して応答データを処理することは避けてください。リクエストが成功したかどうかにかかわらず起動します。

ではなくcomplete、を使用しますsuccess

ドキュメントのAjaxイベントを参照してください。


1
私は成功と完全を往復してきましたが、なぜ完全が優れていると思うのか、詳しく説明していただけますか?
Neil N

1
完全なほうがいいと言っているのではありません。私が言おうとしていたのは、completeの誤解を招く使用を回避する必要があり、応答データを処理できるように成功を使用する必要があるということです。
Artem Barger

2
まあそれはいつも呼ばれます。しかし、私は同意しません。Completeは、読み込み中のgifなどを非表示にするのに最適です。もちろん、応答の処理には成功を使用し、エラーの場合はエラーを使用する必要があります。
redsquare 2009

1
彼は完全ではなく成功を使うことを提案しています。'complete'は、ajaxリクエストが 'complete'の場合に常に起動します。正常に完了したかどうかに関係なく、
SolutionYogi

@redsquare、あなたはまったくあなたが同意しないということを拡張できますか?私はデータプロセスについて言及していましたが、完全なハンドラーで写真を隠したり表示したりする機会を気にしませんでした。
Artem Barger、

24

コールバック付きの「チェイニング」アニメーションイベント。

クリックすると消える段落をアニメーション化したいとします。また、後でDOMから要素を削除する必要もありました。メソッドを単純にチェーンできると思うかもしれません:

$("p").click(function(e) {
  $(this).fadeOut("slow").remove();
});

この例では、.remove()は.fadeOut()が完了する前に呼び出され、段階的にフェードする効果を破壊し、要素を即座に消滅させます。代わりに、前のコマンドが終了したときにのみコマンドを実行する場合は、コールバックを使用します。

$("p").click(function(e){
  $(this).fadeOut("slow", function(){
    $(this).remove();
  });
});

.fadeOut()の2番目のパラメーターは、.fadeOut()アニメーションが完了すると実行される無名関数です。これにより、徐々にフェードし、その後要素が削除されます。


24

同じイベントを複数回bind()すると、複数回発生します。私はいつもunbind('click').bind('click')安全のためだけに行きます


2
これはjQueryに固有のものではありませんが、覚えておくべき重要なことです。
SolutionYogi

11
ライブイベントを使用すると、同じイベントを2回バインドする必要がなくなります。
パワーロード2009

過度に慣れると、ライブには独自の(パフォーマンス)問題があります。あなたがコンテキストを与えることができる1.3.3でより良いです。
redsquare 2009

23

プラグインを乱用しないでください。

ほとんどの場合、ライブラリとユーザーインターフェイスだけが必要になります。単純にしておけば、コードは長期的には保守可能になります。すべてのプラグインがサポートおよび保守されているわけではありません。実際、ほとんどのプラグインはそうではありません。コア要素を使用して機能を模倣できる場合は、強くお勧めします。

プラグインはコードに挿入するのが簡単で、時間を節約できますが、余分なものが必要な場合は、更新を失う可能性があるため、プラグインを変更することはお勧めできません。最初に節約した時間は、後で非推奨のプラグインを変更するときに失うことになります。

賢く使用するプラグインを選択してください。ライブラリとユーザーインターフェイスは別として、私は常に$ .cookie$ .form$ .validate、およびthickboxを使用しています。残りは主に自分のプラグインを開発しています。


2
グリッドはどうですか?自分で作る?
jmav 2009年

はい。プロジェクトからプロジェクトへのデータにはさまざまな方法があります。私は、そのグリッドを理解することが私を真ん中へと助けるだけであり、それから即興しなければならないことを完全に制御することを好みます。
Elzo Valugi、2009年

十分な時間が与えられた場合、一般に、すべてのデータ駆動型の操作(css / html)コードを直接記述することを好みます。言い換えれば、「プラグイン」にデータを渡さないでください。現在のスコープの互換性についてプラグイン(の中盤)を評価するのに十分なほど難しく、将来の要求を忘れます。考える...デザイナー、プランナー、マネージャー、マネージャー、マネージャー。ああ、クライアントとユーザー。しかし、これらすべてのものがあると、十分な「時間」がありません。すでにjqgridを使用してください-あなたは時間を無駄にしています。まだ完了していますか?}
user406905

22

落とし穴:セレクターの代わりにループを使用する。

jQueryの '.each'メソッドに到達してDOM要素を反復処理する場合は、代わりにセレクタを使用して要素を取得できるかどうかを確認してください。

jQueryセレクターの詳細:http :
//docs.jquery.com/Selectors

落とし穴:Firebugなどのツールを使用しない

Firebugは、この種のデバッグ用に実際に作成されました。JavaScriptを使用してDOMをいじくり回す場合は、Firebugのような優れたツールを使用して可視性を確保する必要があります。

Firebugの詳細:http : //getfirebug.com/

その他の素晴らしいアイデアは、ポリモーフィックポッドキャストのこのエピソードにあります: (Dave WardのjQuery Secrets) http://polymorphicpodcast.com/shows/jquery/


1
私は最初のものを何度もやった。ほとんどのjQuery関数は、セレクターから返されたすべての要素を操作することを覚えておく必要があります。
DisgruntledGoat

.eachメソッドを正直に嫌う
Simon Hayter

14

この識別子を正しいコンテキストで使用することの誤解。例えば:

$( "#first_element").click( function( event)
{
   $(this).method( ); //referring to first_element
   $(".listOfElements").each( function()
   {
      $(this).someMethod( ); // here 'this' is not referring first_element anymore.
   })
});

そして、ここでそれを解決する方法のサンプルの1つ:

$( "#first_element").click( function( event)
{
   $(this).method( ); //referring to first_element
   var $that = this;
   $(".listOfElements").each( function()
   {
      $that.someMethod( ); // here 'that' is referring to first_element still.
   })
});

1
+1 jqueryの問題よりもjavascriptの問題の方が多かったのですが、私はこれに何度も失敗していました。
mmacaulay 2010

13

DOM全体を何度も検索することは避けてください。これは、スクリプトを実際に遅延させる可能性があるものです。

悪い:

$(".aclass").this();
$(".aclass").that();
...

良い:

$(".aclass").this().that();

悪い:

$("#form .text").this();
$("#form .int").that();
$("#form .choice").method();

良い:

$("#form")
    .find(".text").this().end()
    .find(".int").that().end()
    .find(".choice").method();

2
$( "。aclass")。this()。that(); よくない!クラスのみのセレクターは遅い
redsquare 2009

これは、1つの選択に対して複数のメソッドを使用するJqueryの機能を示す実例です。私はこの手法にさらに焦点を当てるために、選択を単純に(したがって低速に)しました。
googletorp 2009

10
DOMを繰り返し検索しないようにするのは良いことですが、最後の例は、何が起こっているのかまったくわからない、判読不能な混乱です。フェッチの結果を複数回使用する場合は、変数に格納します。コードをはるかに保守しやすくします。
クエンティン

12

特に.each()で、常に$(this)を意味のある変数にキャッシュする

このような

$(selector).each(function () {
    var eachOf_X_loop = $(this); 
})

12
変数名を考えるのが面倒な場合は、$selfまたはを使用してください$this
gradbot

10

レポマンが言ったことに似ていますが、完全ではありません。

ASP.NET winformsを開発するとき、私はしばしば

$('<%= Label1.ClientID %>');

#記号を忘れます。正しい形は

$('#<%= Label1.ClientID %>');

10

イベント

$("selector").html($("another-selector").html());

イベントのクローンは作成されません。すべてを再バインドする必要があります。

JPのcommentに従って、trueを渡すとclone()はイベントを再バインドします。


4
Clone()は、trueを渡した場合に実行します。
ジェームズ

jQuery 1.3.2のlive()はどうですか?
jmav 2009年

9

同じjQueryオブジェクトの複数作成を回避する

//Avoid
function someFunc(){
   $(this).fadeIn();
   $(this).fadeIn();
}

//Cache the obj
function someFunc(){
   var $this = $(this).fadeIn();
   $this.fadeIn();
}

var $ this = $(this).fadeIn();? エフェクトをキャッシュしていますか?
Jason、

12
それは要素を返します、その呼ばれた連鎖!
redsquare 2009

変数を設定し、それに対して同時にアクションを実行できますか?
Jason

1
確かに、しかしそれを私の言葉にしないでください。それを試してみてください。要素を表すjqueryオブジェクトが返されない場合、次のことが可能だと思いますか?$( '#divId')。hide()。show()。fadeIn().... etc
redsquare 2009

14
それは機能します$this = $(this);が、別の行に置く方が読みやすいと思います。あなたは(混乱せずに)、忘れることができた場合は$this、ちょうどチェーンのすべて:$(this).fadeIn().fadeIn();
パトリックMcElhaney

8

JavaScriptについても同様ですが、jQuery、JavaScriptはCSSに取って代わるべきではありません。

また、JavaScriptがオフになっているユーザーがサイトを使用できることを確認してください(今日ほど重要ではありませんが、完全に使用可能なサイトを用意しておくと便利です)。


6

DOM操作が多すぎます。.html()、. append()、. prepend()などのメソッドは優れていますが、ブラウザでのページのレンダリングと再レンダリングの方法が原因で、頻繁に使用すると速度が低下します。多くの場合、DOMを複数回変更するよりも、HTMLを文字列として作成し、それをDOMに1回含めるほうが適切です。

の代わりに:

var $parent = $('#parent');
var iterations = 10;

for (var i = 0; i < iterations; i++){
    var $div = $('<div class="foo-' + i + '" />');
    $parent.append($div);
}

これを試して:

var $parent = $('#parent');
var iterations = 10;
var html = '';

for (var i = 0; i < iterations; i++){
    html += '<div class="foo-' + i + '"></div>';
}

$parent.append(html);

あるいはこれ($ wrapperは、まだDOMに注入されていない新しく作成された要素です。このラッパーdivにノードを追加してもスローダウンは発生しません。最後に、$ wrapperを$ parentに追加し、DOM操作を1つだけ使用します。 ):

var $parent = $('#parent');
var $wrapper = $('<div class="wrapper" />');
var iterations = 10;

for (var i = 0; i < iterations; i++){
    var $div = $('<div class="foo-' + i + '" />');
    $wrapper.append($div);
}

$parent.append($wrapper);

+1 ...毎秒複数の要素で.html()を使用しています。すべてが遅くなることに気づきました!
User2 14年

5

ClientIDを使用して、ASP.NETプロジェクトのコントロールの「実際の」IDを取得します。

jQuery('#<%=myLabel.ClientID%>');

また、SharePoint内でjQueryを使用している場合は、jQuery.noConflict()を呼び出す必要があります。


11
?これは落とし穴ですか?ASP.NETの動作の回避策です。
SolutionYogi

1
うん。それはjQueryの問題です。これはasp.net webformsのせいです。
redsquare 2009

3
同意した。ただし、これはASP.NETでjQueryを使用する場合に注意する必要があるものです。
Jacobs Data Solutions、

2
OPはasp.netについて言及していませんでした
redsquare 2009

4

jQueryオブジェクトの代わりにIDを関数に渡す:

myFunc = function(id) { // wrong!
    var selector = $("#" + id);
    selector.doStuff();
}

myFunc("someId");

ラップされたセットを渡す方がはるかに柔軟です。

myFunc = function(elements) {
    elements.doStuff();
}

myFunc($("#someId")); // or myFunc($(".someClass")); etc.

3

連鎖の過度の使用。

これを見てください:

this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);

説明


1
それはおかしく見えます、それは一種の難読化です。
Dykam 2009

6
チェーニング(それ自体で)を「過剰」に使用することは困難です。このコードは、JavaScriptの三項演算子を過度に使用しているようです。詳細については、en.wikipedia.org / wiki / Ternary_operation#JavaScriptを参照 してください。
Dan Esparza、

3
コードを保守する必要がないことをうれしく思います。
cdmckay 2009

3

文字列アキュムレータスタイルを使用する

+演算子を使用すると、新しい文字列がメモリ内に作成され、連結された値がそれに割り当てられます。この後で初めて、結果が変数に割り当てられます。連結結果の中間変数を回避するために、+ =演算子を使用して結果を直接割り当てることができます。スロー:

a += 'x' + 'y';

もっと早く:

a += 'x';
a += 'y';

プリミティブな操作は、関数呼び出しよりも高速です。

パフォーマンスが重要なループおよび関数では、関数呼び出しに対する代替の基本操作の使用を検討してください。スロー:

var min = Math.min(a, b);
arr.push(val);

もっと早く:

var min = a < b ? a : b;
arr[arr.length] = val;

JavaScriptパフォーマンスのベストプラクティスで詳細を読む


1

ユーザーにブラウザでhtmlエンティティを表示する場合は、次のように、「テキスト」ではなく「html」を使用してUnicode文字列を挿入します。

$('p').html("Your Unicode string")

1

私の2セント)

通常、jqueryを使用すると、常に実際のDOM要素について心配する必要がなくなります。あなたはこのようなものを書くことができます$('div.mine').addClass('someClass').bind('click', function(){alert('lalala')})--そしてこのコードはエラーを投げることなく実行されます。

場合によっては、これが役立つ場合もあれば、まったくない場合もありますが、jqueryは、空の一致に対応する傾向があります。まだreplaceWithドキュメントに属していない要素で使用しようとすると、エラーがスローされます。私はそれがかなり直観に反していると思います。

別の落とし穴は、私の意見では、prevAll()メソッドによって返されるノードの順序です$('<div><span class="A"/><span class="B"/><span class="C"/><span class="D"/></div>').find('span:last-child').prevAll()。実際には大したことではありませんが、この事実に留意する必要があります。


0

たとえば、20列のテーブルの1500行のような大量のデータでAjaxを計画している場合は、jQueryを使用してそのデータをHTMLに挿入することさえ考えないでください。プレーンJavaScriptを使用します。jQueryは遅いマシンでは遅すぎます。

また、jQueryが着信HTMLのスクリプトタグを解析してブラウザの癖を処理するなど、速度を低下させる時間の半分を実行します。高速の挿入速度が必要な場合は、プレーンJavaScriptを使用してください。


1
-1 .html()関数はネイティブアプローチと同じくらい高速です
cllpse

私に反対票を投じている人は誰もがIEに大量のDOMを挿入してみて、物事が遅くなるのを見ていない。jqueryが遅い理由は、domを単に挿入するのではなく、domにスクリプトがあるかどうかを確認し、IEでそれらを実行するなど、他にいくつかのことを行います。挿入するデータの種類
mkoryak

1
ブラウザのリークなどを心配する必要がない限り、問題ありませ.innerHTMLん。しかし、ユーザーが何時間もタブを開いたままにするようなGmailのようなものを構築している場合は、弾丸をかじって余分な遅延に対処する必要があります。好奇心旺盛な方のために、jQueryの.html()機能は次のとおり
jquery

-1

ほんの数行の通常のJavaScriptで完了することができる小さなプロジェクトでjQueryを使用します。


私は改造されてもかまわないが、あなたの選択を議論してください。
万力

8
-1 jQueryは壊れたAPIを抽象化します。このようにして、コードが機能していることを常に確認できます。jQueryを使用してコードを記述し、ランダムなブラウザーバグが新しいバージョンで導入されたとします。必要なのは、jQueryフレームワークの更新されたバージョンをインポートすることだけです。対して、自分でバグを解決する方法を理解する必要があります。
cllpse

+1は私には理にかなっているようです。数行だけを使用している場合は、バニラJSだけを使用するのが理にかなっています。
アレックス

1
@roosteronacid、あなたの議論は要点を逃しています。ブラウザーがそれほど複雑でないスクリプトに回帰を導入したり、ブラウザーの問題を処理したりすることはほとんどありません。2年前にmootoolsを使用していて、特定の状況下ではIEの要素コンテンツを読み取ることができませんでした。問題を解明するために数時間試してみた後、その部分を単純なjsで書き直しました。したがって、ブラウザのアップグレードが原因で、単純なJavaScriptが失敗するよりも、jQueryが失敗する可能性が高くなります。ライブラリのコードをハッキングするのではなく、いつでも自分でバグを解決したいと思います。
万力

3
couple of lines of ordinary JavaScriptもちろん問題ありません。しかし、それはいつですか?「バニラJavaScriptを使用しないのはなぜですか?」IEでまだ十分にかじられていません...そして、単純な古いJSで単純なことを行うためにどれだけの残骸と定型コードを書かなければならないかは言うまでもありません。
adamJLev

-3

イベントバインディングを理解していません。JavaScriptとjQueryの動作は異なります。

好評により、例:

jQueryの場合:

$("#someLink").click(function(){//do something});

jQueryなし:

<a id="someLink" href="page.html" onClick="SomeClickFunction(this)">Link</a>
<script type="text/javascript">
SomeClickFunction(item){
    //do something
}
</script>

基本的に、JavaScriptに必要なフックは不要になりました。つまり、開発者が通常CSSの目的で利用するIDとクラスを単純に使用できるため、インラインマークアップ(onClickなど)を使用します。


5
詳しく説明しますか?できれば例ですか?
SolutionYogi

7
JavaScriptは、これを行うためにaddEventListener()およびattachEvent()を提供していませんか?
アレックス

2
懸念の分離、男。HTMLとJSを別々に保つ
Don
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.