1 名前:デフォルトの名無しさん mailto:sage [2016/05/22(日) 19:51:33.37 ID:WwOYSBmy.net] JavaScript を自ら学ぶ人のための質問スレッドです。 >>2-4 のテンプレを読んだ上で質問してください。次スレは>>950 が>>2 のテンプレ案(本スレで改善案があれば考慮)を元に立ててください ■質問を書く上で (1) 煽り、コード制作依頼等、人を不快にさせる投稿はご遠慮下さい。公序良俗を守った応対を心がけてください。 (2) 他の人に迷惑をかけるスクリプトの質問はご遠慮ください。 (ブラクラ、[戻る], [閉じる], [クリック] の妨害、画面占有など) (3) 質問者及び議論を行う人はメール欄を空欄にし、名前にレス番を入れることを強く推奨します。回答者はなりすましを判断できませんので、なりすましが現れても自己責任となります。 (4) 常に自発的に調べる心構えを持ってください。 具体的には「自分で調べてから質問する」「回答をもらってわからない単語があればGoogle検索してみる」など。 わからない内容を代わりに調べてくれる回答者をお望みの方は余所で質問してください。 (5) 出来るだけ一般的な用語を使用してください。脳内オレオレ用語は混乱の元です。 (6) 出来るだけサンプルコードを掲示してください。言葉による説明は行き違いが生まれる場合があります。 ※必ず「問題の事象が再現されること」を確認してください。 必要な部分だけ切り出したつもりで現象が再現できていなかったケアレスミスがしばしば見られます。 (7) サンプルコードに HTML が含まれる場合は validator.w3.org/ で [Check] してみてください。 (8) 質問を具体的かつ詳細に書くと回答を得られやすいです。>>2 の質問テンプレートを活用してみてください。 (9) 時にはあなたが望む「答え」だけでなく、「意見」などが寄せられる場合もあります。
486 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 09:31:01.62 ID:E+QhxTx8.net] var F = function(age){ this.age = age; } こう書くぐらいなら function F(age){ this.age = age; } こう書けばいいのに。
487 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 09:35:16.54 ID:E+QhxTx8.net] >>475 中古で安いの探せば3000円ぐらいで買えるのでは?
488 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 13:53:50.48 ID:QTm6YzLa.net] >>472 その方法でどうやってfirst()を呼び出すのかな
489 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 14:40:04.41 ID:G4u6WZVB.net] >>476 後者は旧石器時代の方式だな
490 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 16:54:36.03 ID:+YsNEGfA.net] 内容が等価じゃないのになんで新旧の話になるの
491 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 17:06:35.65 ID:bsniAtVU.net] だよな。 ぜんぜんちゃうやんw
492 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 17:26:41.69 ID:G4u6WZVB.net] >>480 旧石器時代には後者の方法が多用されていたが、それでは問題があるので 近代にはめったに使われなくなったということだが
493 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 19:11:58.00 ID:U5aI2wbo.net] >>482 どちらもES3の頃から存在して使い分けされていたわけだが 関数式を使わない時代っていつだ? せめて、関数名ぐらいつけろよ、といいたい
494 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 19:22:11.65 ID:Homi8Ck7.net] hoisting を嫌う
495 名前:人はこう書くが、新旧いうもんでもない const fn = function fn () {}; [] [ここ壊れてます]
496 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 19:32:23.75 ID:KvDILg9T.net] >>470 そのコードが制限付きで動作している事を理解していればそれでいい - iterable でない(Symbol.iteratorで対応可能) - a[100] = 1; で length を書き換えない(new Proxy で対応可能) - a.length = 5; が働かない(Object.definePropertyで対応可能) - 一部の汎用的ではない関数(concat等)が期待通りに動作しない(独自にコードを書けば対応可能)
497 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 23:45:53.30 ID:W5L1fKQF.net] >>485 詳細にありがとうございます!! > - a[100] = 1; で length を書き換えない(new Proxy で対応可能) > - a.length = 5; が働かない(Object.definePropertyで対応可能) ありがとうございます。それらの不具合は気付いていませんでした。 let a = new Proxy(new A, { set: function(target, property, value, receiver) { let i = parseInt(property); if (i === i && target.length <= i) target.length = i + 1; // a[n] = x;に伴うlengthの更新に対応。 else if (property === 'length' && value < target[property]) { target.splice(value, target[property] - value); // a.length = n;の代入時の挙動(の一部?)をケア。 } target[property] = value; return true; } }); Object.defineProperty(a, 'length', {enumerable: false, writable: true, value: 0}); これでとりあえずケアできているようではありますが、 Proxyに非対応なブラウザもあるようなので注意ですね。
498 名前:デフォルトの名無しさん mailto:sage [2016/06/09(木) 23:47:09.04 ID:W5L1fKQF.net] >>485 > - iterable でない(Symbol.iteratorで対応可能) 現時点ではワケが分かっておりませんが頂いたヒントは大事に記憶しておきます。 > - 一部の汎用的ではない関数(concat等)が期待通りに動作しない(独自にコードを書けば対応可能) これも今確認しました。concat使えないの悔しいです。 Object.defineProperty(a, 'concat', {enumerable: false, value: function () { return A.prototype.concat.apply(this.slice(), arguments); }}); しかしまぁこういうのを結局書いていくのは悔しいですね。 ちょっとラクしたいだけなのに段々大袈裟になっていくという…。
499 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 00:39:24.13 ID:G+eNnn4N.net] >>485 言っていることは間違いではないが、(結果的にでも)無垢な少年を騙すのはいかがなものか、、、 >>487 てかお前、それ自分でやってておかしいって思うだろ? ここの連中は仕様には詳しいが、コードを書いてないから、実装方式については話半分に聞け。 (まあ今回は君が勝手に突っ走ったのであり、騙したわけではないとは思うが) そのコードを見る限り、君は自力で解に辿り着けるはずだ。 俺がぱっと思いつくだけで解は3通りある。当たりかどうかは答えてやるから、冷静に考えてみろよ。
500 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 01:01:27.01 ID:DHroUP1C.net] javascriptについて質問があります。 初回起動時のform(画面項目)の値と現在の値を比較して1つでも変更があった場合にはポップアップを表示するといった処理を実装したいのですが何か良い方法があれば、ご教授お願い致します。
501 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 01:02:08.05 ID:DHroUP1C.net] >>489 続き はじめはその項目のvalueとdefaultValueにて比較できると思いましたが、defaultValueは画面を再描画するタイミングで取得しますが、行いたい処理の途中でアクションが走り必ず再描画されるタイミングがあるためその方法では比較できないことに気づきました。
502 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 01:02:31.57 ID:DHroUP1C.net] >>490 続き (また項目の入力チェックなのでエラーになった場合にも) なので再描画されても、初期表示時の
503 名前:値と現在の値を比較する方法はないでしょうか… ちなみに画面はJSPにて実装しており、項目はtextやradioやoptionなどあります。 [] [ここ壊れてます]
504 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 01:28:33.37 ID:rm3c6PtR.net] >>482 https://mitsuruog.github.io/javascript-style-guide/#%E9%96%A2%E6%95%B0functions 7.1 関数式より関数宣言を利用してください。 なぜ? 名前が付けられた関数宣言はコールスタックで簡単に見分けることができます。 さらに関数宣言は関数の本体が巻き上げられます。それに対し、関数式は参照だけが巻き上げられます。 このルールにより、関数式の部分を常にアロー関数で置き換えて利用することができます。 // bad const foo = function () { }; // good function foo() { }
505 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 01:45:19.78 ID:rm3c6PtR.net] function Klass() { } という書き方が古臭いとかいうことは当然なくて、 特定の場合では、var hoge = function() {} と書くべきという話を、 頭の悪い、なーんも考えてない馬鹿が、 絶対にvar hoge = function() {} と書かないといけない、 これからはfunction hoge() {} と書いてはならないんだ!って 言ってるだけ。 function Klass() {} という書き方が古くなったとか 聞いたこと無いし、使っていいし、むしろ推奨されている。 ほんと何も考えてない、誰かにaといわれれば 理由も考えずに妄信的にaばっかり使う、そんなやつが多いよなw
506 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 02:03:50.61 ID:G+eNnn4N.net] >>493 俺は仕様には詳しくないから具体的に何が問題になるのかは分からないが、 基本的に「普通」の書き方にしておいた方がいいと思うぞ。 というか、何故お前らが妙なこだわりを持つのか、かなり謎なんだが。 > var Person = function () { > console.log('instance created'); > }; > > var person1 = new Person(); > var person2 = new Person(); > https://developer.mozilla.org/ja/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
507 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 02:06:08.67 ID:rm3c6PtR.net] >>494 そこに書いてあるだろw // Student コンストラクタを定義する function Student(firstName, subject) { // 親のコンストラクタを呼び出す。呼び出しの際に "this" が // 適切に設定されるようにする (Function#call を使用) Person.call(this, firstName); // Student 固有のプロパティを初期化する this.subject = subject; }; これは普通の書き方。
508 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 02:18:52.51 ID:G+eNnn4N.net] >>495 おっと?これは失敬。 ということはこれについては統一見解はなくて、どっちでもいいって事だな。
509 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 02:49:43.87 ID:OOVSLX1/.net] >>495 引用元もそうなってたけど、 最後のセミコロンはいらないよねぇ。
510 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 05:22:06.39 ID:naViO+5c.net] どっちでもいいわけないだろ アホかこいつ
511 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 08:02:38.57 ID:52VYMGKm.net] >>486-487 いろいろと挙動がおかしいのでよく確認してみるといい 繰り返すが、A.prototype.concat は汎用的ではない https://jsfiddle.net/cw8umnqd/
512 名前:デフォルトの名無しさん [2016/06/10(金) 08:21:29.14 ID:o8hFzx97.net] 結局、コンストラクタ用の関数を書くときにも、 関数式よりも、巻き上げのある関数宣言の方が、良いのか?
513 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 08:31:51.96 ID:52VYMGKm.net] >>487 > しかしまぁこういうのを結局書いていくのは悔しいですね。 ビルトイン関数には汎用的なものと汎用的でないものがあって、汎用的でない機能をエミュレーションするのは単純じゃない (とはいえ、JavaScriptは汎用的なプロパティ/関数があるだけエミュレーションするのは楽な方だと思う) 内部的に new Array を保持しておき、new Proxy で透過的に new Array を参照すらば比較的楽に実装出来るが、コストがかかる 完璧なエミュレーションに拘らないのであれば妥協も必要
514 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 08:33:32.04 ID:INHt9BTU.net] >>489 この状態と比較したい、って状況で、「画面の対象のコントロール回ってvalueを;かなんかで繋いで返す」関数作って、それ呼んで値を覚える。 変更チェックかけるときに、もう一回その関数呼んで、覚えたものと===で無ければ何かしら変更があった。 ってやってるよ。 「対象のコントロール」にはclassにcheckDatumとか空クラスつけとけばそれで列挙できるし。
515 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 08:47:37.80 ID:BhzVNYOI.net] varとfunctionが同じだのセミコロンいらねえだの こんなのが毎日偉そうに能書き垂れてんの? そりゃサンプル出せって言われたら黙るわけだ
516 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 09:33:17.22 ID:o8hFzx97.net] >>485-487 Groovyのメタプログラミングなら、 実行時に既存のクラスに、メソッドを追加するなら、Category・Mixin。 メソッド・プロパティを変更・追加するなら、ExpandoMetaClass そういう複雑極まりない方向へ進むのは、最初から考え方がおかしいのでは?
517 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 09:36:28.17 ID:+uuPJDCE.net] >>500 > 関数式よりも、巻き上げのある関数宣言の方が、良いのか? 何も考えてねぇ馬鹿は、変数の巻き上げの問題(もちろん理由がある)の話を、 全く関係ない関数にまで適用しようとする(笑) 理由は何だよw ブロック内だけで使う関数など、関数式でなければいけない場合もあるが 通常は関数宣言の方がいいに決まってるだろ。 C言語は宣言された関数しか使えなかったため「前方宣言」などという 物が生み出されてしまったが、それ以降、それ以外の殆どの言語は 関数はどこで宣言しても(巻き上げされたかのように)使うことが出来る。
518 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 09:40:10.83 ID:4srunpG+.net] 所詮は自己満足の世界なんだよ
519 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 09:40:12.48 ID:+uuPJDCE.net] 普通に関数に名前(コンストラクタも含む)をつければいいのに、 「さいきんのクールなプログラマはvarで関数入れて使うんだぜ! 今時関数に名前つけるなんてのは旧石器時代だな!」とか言ってるんだぜw バカっぽいだろ?事実なんにも考えてない。 デバッガ時に関数名表示がでなくなる問題があるというのにな。
520 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 10:33:45.27 ID:GFWTaLNc.net] >>483 > どちらもES3の頃から存在して使い分けされていたわけだが 誰もが(いいすぎ)使い分けるようになったのは、近代になってから > 関数式を使わない時代っていつだ? だから旧石器時代だって ゼロ年代初頭あたりまで
521 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 10:36:19.23 ID:GFWTaLNc.net] >>493 > function Klass() {} という書き方が古くなったとか > 聞いたこと無いし、 グローバルネームスペースを汚染する弊害について聞いたことないのか
522 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 11:04:28.13 ID:rddDxbo4.net] >>509 クロージャの中でやる分には大丈夫なんじゃないの?巻き上げられたっけ?
523 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 11:31:26.83 ID:xHgczCBO.net] 今時グローバル汚染するようなアホおまえくらいだから
524 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 11:46:24.26 ID:XqAkh7YW.net] なんであんなに無名を濫用するのかと思ってたが そんなしょうもない理由だったのか
525 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 14:12:05.29 ID:dpRBFPup.net] >>509 聞いたことないが、その弊害の発生条件は?
526 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 14:36:22.02 ID:4srunpG+.net] そうだよな 汚染ってなんだよ
527 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 15:06:36.55 ID:LT2C5Mf1.net] prototype使って、汚染しちゃうのは初心者がやってしまう失敗
528 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 15:59:08.90 ID:DxAsZ/F5.net] 1個くらいならバレないんじゃない?
529 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 16:05:16.91 ID:
] [ここ壊れてます]
530 名前:3bO9ZAmE.net mailto: Object.prototype.hogeにバーカって書いとけばいいのか [] [ここ壊れてます]
531 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 18:15:57.76 ID:LT2C5Mf1.net] コンソールに出すの? アラートで出すの? アラートで出たら、めちゃくちゃ怖いかもww
532 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 19:06:13.75 ID:qrHSyLm3.net] prototype汚染という考え方も古くなってきた感はあるが… しかし、風呂敷を広すぎではないかね 元々はprototuype汚染の話ではなかったわけで段々と本題がずれてきているように思う
533 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 19:27:07.34 ID:qrHSyLm3.net] >>489-491 画面を再描画するならサーバサイドの処理があるはずだが、それはJavaScriptで実装すべき案件なのかね フォームで値を受け渡してサーバサイドで処理、セッションを使う等、いくつか対策があるはずだが jsを使うなら再描画させずに動的にDOMを書きかえれば済むが、マルチポスト先を読む限りではこの質問者にはハードルが高そうだな https://teratail.com/questions/37462 https://teratail.com/questions/37489
534 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 20:02:15.97 ID:G+eNnn4N.net] >>500 少なくとも文法上は大差ないのだろう。MDNにも説明はある。 > 全ての関数は実際には Function オブジェクトです。 > Function コンストラクタか関数宣言か関数式か > https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope new Functionや非トップレベル関数(strict modeでは禁止)も含めて書いてあるから余計に分かりにくくなっているが、 要するにどうでもよさそうだ。 現実的にはコンストラクタだけ前方参照できてもプロトタイプが用意できていないから意味がない。 だから関数式の方が似合っている気はする。 ちなみに汚染については変数名か関数名かだけでどちらも汚染する。 また、デバッグ時にこんなところが関数表示されたところで嬉しくない。 どのみちコンストラクタが呼ばれればコールスタックには載るし、ブレークポイントも当てられる。 お前らは異様に文法にこだわることを止めて、もっとコードを書いた方がいい。 指摘が間抜けなのは、コードを書いてないからだ。(実践的ではない) ○○の問題がある(キリッというのは正しいが、それが重要なことなのか、わりとどうでもいいことなのか、区別が出来ていない。 >>520 > マルチポスト先 よく見つけたなw というかこの手のモラルがない奴、急に増えたよな?何か理由があると思うのだが。 昔から居たけど、マルチポスト先が増えたから発覚しやすくなっただけか?
535 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 20:08:51.44 ID:RNr8lFlW.net] >>499 どうもありがとうございます。おかげで気がついてしまいました。 concatはArrayを受け取ってArrayを返すつもりで>>487 では書きましたが、 よく考えると今回拡張したA(以下単にA)を引数に受け取りたいですし、 返す結果もよく考えるとAであったほうが嬉しいかもしれません。 実装の手間という面だけでも尻込みしつつあったんですが、 いまや設計の方針と言う面でも相当きな臭いというか。 concatの返す値が決められなくて不気味。使うときに不安。 仮にsliceやspliceなどのもまとめて全部Aを返すように統一したとしても、 最終的にはArrayとAの二系統が混在する世界になっちゃうわけで不気味。 >>501 > 完璧なエミュレーションに拘らないのであれば妥協も必要 そのつもりだったんですがいざ用意してみると、 欲が出るわ粗が目立つわ方針で不安になるわで散々でした。 今後は生のArrayのみを運用していくつもりです(結論)。 >>504 ありがとうございます。Groovyはぐぐったことすら無いので分かりません。 > そういう複雑極まりない方向へ進むのは、最初から考え方がおかしいのでは? はい。完全にそのとおりです。
536 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 21:47:53.40 ID:qrHSyLm3.net] >>522 > 今後は生のArrayのみを運用していくつもりです(結論)。 それはそれで一つの答えだが、やや狭い世界になっていると思う > 最終的にはArrayとAの二系統が混在する世界になっちゃうわけで不気味。 2つの世界が存在することは問題なくてそれが息をするように自然に使えるかどうかが問題ではないだろうか mew Array と new A を行き来する世界はよくないが、それぞれの世界で完結する処理を書けるのならそれでいい どちらかといえば、設計指針を決めかねて迷っているのだと思うが… 基本的には new A は A だけで閉じた世界(new Array を返してはならない)であるべきなので A#concat は new A を返すべきだと思う 逆に A#push は汎用的なので特別な事をせずとも new A を返す このように汎用的な関数を基本的には使って非汎用関数に対しては Polyfill を作る要領でコードを書いていけばそれなりのものができるだろう 別の設計指針としては new Map を new ArrayMap 的な設計にして作り直しても面白いかもしれない new Map は関数でsetter/getterを作るので new Array よりは互換コードを書きやすいはずだ 機会があれば、是非新しい世界を作ることに挑戦してみてほしい
537 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 21:58:16.74 ID:MdFWcZSW.net] こういう人に読ます気がない文章は目の前で破り捨てるに限る
538 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 22:12:29.26 ID:AlU+uWXE.net] ES6だとプロトタイプ汚染がないのかと思ったけどもしかして新機能がない? 結局 Object.defineProperty(...){........} と書かんといけんのか
539 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 22:18:01.79 ID:G+eNnn4N.net] この程度で躓くのならもっと長いMDNは当然無理で、池沼のままなのもむべなるかな
540 名前:523 mailto:sage [2016/06/10(金) 22:51:59.24 ID:qrHSyLm3.net] 読みにくくてすまん どういうわけが改行コードが一部消えているな…
541 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 23:08:39.56 ID:+uuPJDCE.net] *∧ ∧:・。゚*。 : ・ 。 ゚ *★. (*・ω・*) ゚ *。* *〇 〇………………………** 祝☆jQuery 3.0 リリース https://blog.jquery.com/2016/06/09/jquery-3-0-final-released/ **………………………………* + JavaScript & jQuery 質問用スレッド vol.6 + [無断転載禁止]©2ch.net echo.2ch.net/test/read.cgi/hp/1465566635/
542 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 23:10:44.42 ID:+uuPJDCE.net] >>509 > > function Klass() {} という書き方が古くなったとか > > 聞いたこと無いし、 > グローバルネームスペースを汚染する弊害について聞いたことないのか なにいってんだおめぇ? var Klass = function() {} という書き方をしても グローバルネームスペース汚染してるだろw function hoge() { function Klass() {} } ↑Klassがグローバルネームスペース汚染ってどういうこと?w
543 名前:デフォルトの名無しさん mailto:sage [2016/06/10(金) 23:13:14.16 ID:+uuPJDCE.net] >>524 同じこと思ったw
544 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 00:01:17.78 ID:MQjYfq34.net] ライブラリスレが復活してた JavaScript ライブラリ総合質問所 vol.5 [無断転載禁止]©2ch.net echo.2ch.net/test/read.cgi/hp/1465399470/
545 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 08:41:10.92 ID:MQjYfq34.net] jQuery推しが酷いと思ったらテンプレ改変されていたのか
546 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 13:03:48.93 ID:n8nif7qi.net] 今更かよ ここ乗っ取られスレだよ
547 名前:デフォルトの名無しさん [2016/06/11(土) 13:06:25.18 ID:ijG8u0pc.net] java script初心者です。ご教授願います m(_ _)m 初めてpromiseで簡単な非同期処理を書いたんですが、一応動くもののどうにもコードがしっくりきません もっとシンプルにできたり、適切な書き方があるところがあったら教えてください 内容は単語queryに対応する画像検索結果がローカルストレージになかったら外部APIに問い合わせるというものです
548 名前:534 mailto:sage [2016/06/11(土) 13:09:15.52 ID:ijG8u0pc.net] function getCachedData(query) { return new Promise(function(resolve, reject){ chrome.storage.local.get(query, function(cachedJson){ if (isExist(cachedJson)) { resolve(cachedJson[query]); } else { reject(); } }); }); } function getImageData(query) { getCachedData(query) .catch(function(){ return fetch(window.googleCustomSearchApi + query) .then(function(response) { return response.json(); }).then(function(json){ chrome.storage.local.set({[query]: json}); return json; }); }).then(function(json) { createPopUp(json.items[0]); positionPopUp(); }).catch(function(err) { console.error(err); }); }
549 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 13:14:41.27 ID:ijG8u0pc.net] インデント潰れてしまった・・・ preタグで再投稿 <pre> function getImageData(query) { getCachedData(query) .catch(function(){ return fetch(window.googleCustomSearchApi + query) .then(function(response) { return response.json(); }).then(function(json){ chrome.storage.local.set({[query]: json}); return json; }); }).then(function(json) { createPopUp(json.items[0]); positionPopUp(); }).catch(function(err) { console.error(err); }); }</pre>
550 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 13:21:07.32 ID:e5AOazPt.net] >>534 この記事が参考になるかな gao-tec.seesaa.net/article/427643074.html
551 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 13:33:33.96 ID:ijG8u0pc.net] >>537 ありがとう 3回読んできます
552 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 13:39:59.04 ID:n8nif7qi.net] >>534-535 2chはHTMLタグ使えないからjsFiddleみたいな投稿サイトを使うといいよ 前まではテンプレにあったんだが 一見ネストが深いように見えるけど結構シンプルに纏まってると思う fetchの部分を外に出せば視認性がよくなるんじゃないのって程度 しいて言えばgetImageData内でPopUp関数を呼び出してるのがしっくりこない getImageData自身もPromiseインスタンスを返してresolve(json)するのがいい
553 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 13:59:44.48 ID:ijG8u0pc.net] >>539 今日だけ師匠と呼ばせてください 自分でもそこはなんか気持ちわるかったんです promiseチェインがcatchで始まった挙句、頭でっかちで でも外に出すというのはどうやるんでしょう・・・ fetchからの処理をまとめた関数(返り値は最終的なjsonデータのpromise)を外に定義して、それを呼び出す感じですか? そしてgetImageDataがPromiseインスタンスを返すように書き換えるには、ええと・・・(思考フリーズ)
554 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 14:41:46.28 ID:n8nif7qi.net] >>540 getCachedDataと同じ書き方をfetchとgetImagedataでやるだけだよ
555 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 15:16:00.71 ID:NAulAg4n.net] >>539 > 一見ネストが深いように見えるけど結構シンプルに纏まってると思う え? ちょっとまてよ?
556 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 15:45:12.80 ID:NAulAg4n.net] >>540 これgetImageDataの中でキャッシュあるか調べてるからいけないんだよ。 一般論として、キャッシュというのは存在を意識しないようにコードにするべき。 関数の役割ってのが書いてないし、これだけじゃ読み取れないから難しいんだが、 そのgetImageDataっていうのは画像があれば、ポップアップウインドウを表示するんだろう? であれば、getImageData() ではなくて showImageData() とかいう名前にするべき。 そして、getCachedData()ではなく、こっちをgetImageData()にするべき。 getImageData()っていうのは単にImageDataを返すだけ、その中でキャッシュを使っていようが 使っていまいが関係ないし、別の仕組みのキャッシュを使うかもしれない。がgetImageData()を 使う人からはそんなこと知ったことじゃない >>535 のコードは、chrome.storage.local を使っている箇所が、getCachedDataと getImageDataの2つに分かれているだろ? 関数の役目が明確に分離されていないからそうなる。 非同期の書き方の問題の前にまずやることがあるってことさ。 あと、スペース1個でインデントは見にくいからやめろw 最低でも2個だ。
557 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 15:47:35.86 ID:NAulAg4n.net] で、これが修正コード例だ。 やりたいならばchrome.storage.local.getをPromise化する事もできるがね。 function getImageData(query) { return new Promise(function(resolve, reject) { chrome.storage.local.get(query, function(cachedJson) { if (isExist(cachedJson)) { resolve(cachedJson[query]); return; }
558 名前: fetch(window.googleCustomSearchApi + query) .then(function(response) { var json = response.json() chrome.storage.local.set({[query]: json}); resolve(json); }) .catch(function(err) { reject(err); }) }); }); } function showImageData(query) { getImageData(query) .then(function(json) { createPopUp(json.items[0]); positionPopUp(); }) .catch(function(err) { console.error(err); }); } [] [ここ壊れてます]
559 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 15:56:05.66 ID:NAulAg4n.net] で、どうしてもgetImageData()の中身をPromise化したいならこんな感じかね? 動かせる環境がないので、これで正しく動いているかはしらない。 元のコードに合わせてisExistがfalseならreject()しているが、 nullを返して、データがnullだったらfetchしたほうがいいような気もするが。 function getImageData(query) { return new Promise(function(resolve, reject) { chrome.storage.local.get(query, function(cachedJson) { if (isExist(cachedJson)) { resolve(cachedJson[query]); } else { reject(); } }).cache(function()) { return fetch(window.googleCustomSearchApi + query) }).then(function(response) { var json = response.json() chrome.storage.local.set({[query]: json}); return json; }); }
560 名前:534 mailto:sage [2016/06/11(土) 16:03:43.18 ID:ijG8u0pc.net] >>543 自分でああでもないこうでもないと考えてコードを修正していたら返信遅れました か ら く ちwwww と思って訂正コードと自作スパゲッティを見比べたらグウの音も出ませんでした この整理されたしっくり来る感じ 勉強になります あとは・・ エラーハンドリングについてわからないところがあります!
561 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:07:35.34 ID:ZhHlBSFM.net] >>537 良い記事だ。 が、前から疑問なのだが、何故お前らはネストにこだわるのだ? 俺は展開して書いていて、特に問題を感じない。 要求が「脳筋無限ループの例ぐらい単純な構造で」「非同期処理を実現する」 「処理は上から下へ」「ネストが深くならない」ならば、これでいいと思うのだが。 好きずきはあると思うが、このような場合にでも例としても出てこないのは謎なんだが。 function Main(){ console.log("a"); setTimeout(Main_1,2000); function Main_1(){ console.log("b"); setTimeout(Main_2,1000); } function Main_2(){ console.log("c"); } } Main();
562 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:12:31.73 ID:NAulAg4n.net] >>545 は本当に動くかどうかわからない。 実はcacheのあとにthenをつなげたことないんでねw まあ関数の中を試行錯誤すりゃできるだろうと思うけど。 最悪>>544 でいいし。 "何をする" 関数か?(クラスか?)ってことをよく考えることが重要。 動くようにコードを配置するんじゃなくて、何をする関数か?を定義して それに合わない所はたとえコードが増えても外にだすべきだし、 入れるべきだと思えば、どうにかして持ってくる。 もちろん場合によっては、"何をする" の定義を変えてもいいけど はっきり定義させることが重要。 例えば、このgetImageData()はchrome.storage.local を使うことが前提になってるけど、 いろんなキャッシュの仕組みを入れ替えられるようにする関数(というかクラスになるだろうけど)を定義すれば getImageData()の中からはchrome.storage.localが消えて、キャッシュの仕組みを 入れ替えられるだけのことをするクラスができあがるわけ。
563 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:15:59.14 ID:NAulAg4n.net] >>547 > が、前から疑問なのだが、何故お前らはネストにこだわるのだ? やりかけで覚えておかなければならないことが増えるからだよ。 Aが終わってからBをして、Bが終わってからCをする。というやり方よりも Aの途中でBをして、Bをしているその途中でCをするほうが疲れるから。 Cが終わったら、Bはどうなったんだっけ? そしてAはどうなったんだっけ?って 戻って行かないといけないからね。 言い換えると可読性の問題だからだ。 非同期とかそういうところが問題になってるんじゃない。 やりかけの作業を脳に貯めておくと言うところが問題なんだよ。
564 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:20:02.55 ID:NAulAg4n.net] >>547 あと、そのコードの問題は「名前」が増える。 名前が増えるっていうのも、いちいち記憶して おかなければならないことだから面倒 限りある記憶領域は、記憶する価値のある物、 汎用的でどこでも使えることだけに絞る必要がある。 覚える価値がないものは覚えなくていい。 そのコードは関数の
565 名前:シ前が増えているだけだが、 クロージャーじゃなくなっているから、変数の名前も増えるだろうね あと処理があちこちに飛ぶから、コードが長くなったらスクロールする回数も増えるよw もちろん関数が長ければ分けるが少なければその場に埋め込むという意味だ。 [] [ここ壊れてます]
566 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:26:52.64 ID:ZhHlBSFM.net] >>549 そうか?ぶった切られているだけで、実は同じだろ。追加部分を見やすいように編集しておいた。 同期的に「放り投げて終わり」にしたいという気持ちも分かるが、無理にネスト/Promise化するより見やすくないか? 脳内 s/setTimeout...function(){// で全く問題ないはずだが。 function Main(){ console.log("a"); setTimeout(Main_1,2000); // 追加 function Main_1(){ // 追加 console.log("b"); setTimeout(Main_2,1000); // 追加 } // 追加 function Main_2(){ // 追加 console.log("c"); } // 追加 } Main();
567 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:29:29.39 ID:tWgkOxEq.net] もうそれはasync/await、もしくはgenerator/yieldを使うしかないよ。
568 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:35:45.96 ID:NAulAg4n.net] >>551 サンプルコードでやってるからだめなんだよw お前、頭の中で、このコードはsetTimeoutしかない。Main以外の名前は存在しない。 しかもそれぞれ短いコードで呼び出す順番に並んでいるいう「記憶」に頼ってコード読んでるだろ? それはお前だから出来ること。(短いから俺でも出来るけどさw) 実際に業務ではそういう「記憶」には頼れない。コードはもっと長いし 汎用的じゃないものは名前も覚えられない。(何日も経ったら忘れる) 汎用的でないものには、適切な名前をつけることも難しい。 仮にそのコードのまま、記憶に頼れないように書き換えてみようか? さっきと同じように気楽に読めるかい? どこでどう呼び出しが行われてるか探すだろ? function Kjads(){ console.log("a"); function cgrd(){ // あrtが console.log("c"); } // あrtが badf(fgaz); // あrtが function fgaz(){ // あrtが console.log("b"); asdfa(cgrd); // あrtが } // あrtが } Kjads();
569 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:36:17.69 ID:ZhHlBSFM.net] >>550 「名前」が増えるのは事実だけど、関数内関数で隠蔽するし、 そもそも処理を必ず「上から下に」書くのでその点は問題にならない。 つまり、このように展開した場合、その関数は直前のsetTimeoutからしか呼ばれない。 したがって、覚える必要はないし、 処理があちこちに飛ぶこともない。(
570 名前:ただこれはそう書く、ということだが) ちなみにクロージャーにはなっている。 > もちろん関数が長ければ分けるが少なければその場に埋め込むという意味だ。 いや、結構糞長い奴もそこに書くよね? $.ajaxとかその場にだらだら全部書くほうが普通じゃないか? [] [ここ壊れてます]
571 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:39:28.40 ID:NAulAg4n.net] >>554 もうそろそろ>>553 をみて、記憶に頼ってるなって自覚したはずw > ちなみにクロージャーにはなっている。 なってない function Main(){ var v = 1 setTimeout(function() { console.log(v); }, 1000); } ↓ エラーになる function Main(){ var v = 1 setTimeout(Main_1, 1000); } function Main_1(){ console.log(v); } 変数vを渡すために、名前が増えるwww
572 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:39:52.50 ID:ZhHlBSFM.net] >>553 ああ、ちょっと遅れたが、それは既に書いたように、俺内コーディングルール 処理を必ず「上から下に」書く で対応している。というか、そもそも意図的に可読性を落とす必要はないだろ。 「上から下に」書けるところでは「上から下に」書くのが常識だろ。 名前もこの手の場合は XXX_1, XXX_2, ..... と順に付けていく。おかしな名前を付けたりすることはない。
573 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:40:41.06 ID:NAulAg4n.net] >>554 > $.ajaxとかその場にだらだら全部書くほうが普通じゃないか? 下手なやつが多いだけ。 俺は関数に分けるべき理由が生まれれば当然分ける。
574 名前:534 mailto:sage [2016/06/11(土) 16:40:58.22 ID:ijG8u0pc.net] >>544 の綺麗なコードを見る前に、API問い合わせの部分を関数に分離しようと思って、fetch用の追加のエラーハンドリングも加えてこう書いてしまったんですね(お蔵入りですが、このなかで疑問が沸いたので・・) function googleCustomSearch(query) { return fetch(window.googleCustomSearchApi + query) .then(handleNetworkError) .then(response => response.json()) .then(json => { chrome.storage.local.set({[query]: json}); return json; }) .catch(err => { // 【ここが疑問】 }); } function handleNetworkError(response) { if (!response.ok) { throw new Error(reponse.status, response.statusText); } return response; }
575 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:44:00.74 ID:NAulAg4n.net] >>556 > 処理を必ず「上から下に」書く > > で対応している。というか、そもそも意図的に可読性を落とす必要はないだろ。 > 「上から下に」書けるところでは「上から下に」書くのが常識だろ。 ほらなw お前の常識w 何処かで、function hoge() {} じゃなくて var hoge = function() {} って 書けって言っていたやつが居るが、 (ちなみに俺はその必要がないならばfunction hoge()って書け派) これは上から下に書けない。 hoge(); var hoge = function() {} hage() var hage = function() {} まあ 「上から下に」"書けるところでは" って書いているところからもわかるように 書けない場合があると自覚してるんだろうがw その書ける所と書けない所、ここは書ける所だという前提を知ってるのも「記憶」だよねw
576 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:44:38.09 ID:ZhHlBSFM.net] >>555 何が言いたいのか分からんが、これでいいか? function Main(){ var count = 0; console.log('a: '+count++); setTimeout(Main_1,2000); function Main_1(){ console.log('b: '+count++); setTimeout(Main_2,1000); } function Main_2(){ console.log('c: '+count++); } } Main();
577 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:46:15.25 ID:NAulAg4n.net] >>560 勝手にコード書き換えんなよw function Main(){ var count = 0; console.log('a: '+count++); setTimeout(Main_1,2000); function Main_1(){ var v = 1; console.log('b: '+count++); setTimeout(Main_2,1000); } function Main_2(){ console.log('c: '+count++); console.log(v); // エラーになる } } Main(); それともお前、ローカル変数は作るな。 全部クラス変数にしろとか言う派なのか?www
578 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:50:41.71 ID:NAulAg4n.net] >>558 いやw 何が疑問なのかさっぱりわからないんだがwww
579 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:51:15.94 ID:ijG8u0pc.net] googleCustomSearchの呼出元にhandleNetworkErrorで起きたエラーを伝えるためには、 1.最後のcatchのなかでもう一度new Error(err)を投げる 2.Promise.reject(error)を返す 3.そもそも書き方が悪い、 >>544 みたいにfetchをnew Promiseでラップして、reject(err)してください どれが適切なんでしょうか
580 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 16:54:15.22 ID:ZhHlBSFM.net] >>561 いや勝手に書き換えたのはお前だろ。 >>555 のコードでは var v=1 は Mainの中じゃないか。 Main_1の中で新しい変数が必要なら、 ・Main_2をMain_1内に移動する(ネストが増える) ・v を Main内で定義しておく のどちらかだろ。俺なら後者的アプローチを取ることが多いと思う。 ただ、途中で変数が必要なときも管理しなくていいというのは確かにメリットかもな。
581 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 17:02:05.55 ID:ZhHlBSFM.net] >>559 それはクラスの時の話だ。 クラスの場合は、コンストラクタだけ呼べても意味がないだろ。 Hoge.prototype.XXX = function(){...}; の記述が「順序が必要」なので、どのみちその記述以降じゃないと new Hoge() 出来ないんだよ。 誰も普通の関数 hoge を全部 var hoge = function(){} と書けとは言ってない。 お前が話について来れてないだけ。 まあ分かった、お前が「文法的に読み込める方が善」というのならそれでいい。 で、他の連中もそうなのか?
582 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 17:09:12.67 ID:ZhHlBSFM.net] >>557 ちと細かいがこれにも言っておくと、 > 俺は関数に分けるべき理由が生まれれば当然分ける。 彼等は「関数に分けるべき理由」が分からないのではなくて、その必要がないという判断でそこに書いているんだよ。 下手なわけではない。 通常、$.ajaxの場合はそこでしか使われない関数になるから、ネスト派ならそこにだらだら書く方が自然なんだ。 ただ、「ネストが深くなる」のが嫌いなくせに、「ネストでしか書かない」のが俺には疑問なんだ。
583 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 17:31:06.27 ID:aOjkg+66.net] >>523 毎度ありがとうございます。 > 機会があれば、是非新しい世界を作ることに挑戦してみてほしい 今回のことで色々勉強させてもらいましたので、 次に生かせたいと思います! 色々ありがとうございまし!
584 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 17:31:44.01 ID:aOjkg+66.net] おっw ×まし! ○ました!
585 名前:デフォルトの名無しさん mailto:sage [2016/06/11(土) 18:02:04.85 ID:NAulAg4n.net] >>566 > 下手なわけではない。 > 通常、$.ajaxの場合はそこでしか使われない関数になるから、ネスト派ならそこにだらだら書く方が自然なんだ。 > ただ、「ネストが深くなる」のが嫌いなくせに、「ネストでしか書かない」のが俺には疑問なんだ。 <
586 名前:br> いや、俺は$.ajaxでDeferred使うし、やっぱり下手なだけじゃね? [] [ここ壊れてます]