+ JavaScript の質問用スレッド vol.131 +
■ このスレッドは過去ログ倉庫に格納されています
JavaScript を自ら学ぶ人のための質問スレッドです。 次スレは>>950 が(本スレで改善案があれば考慮して)立ててください ■規則/推奨ルール ・メール欄を空欄にし、名前にレス番を入れることを強く推奨(なりすまし防止) ・質問内容は具体的に。言葉だけでなく、出来る限り再現性を確認したサンプルコードの掲示。 ・質問テンプレートの利用推奨。 ・質問への「答え」だけでなく「意見」を出しても良い。 ■禁止行為 ・丸投げ質問 ・迷惑スクリプトの質問 ・オレオレ用語の使用(一般的な用語を使用する事) ・煽り、批判等の他人を不快にさせる行為(批判の代わりに「AよりBが良い」のような代案を出す事) ■質問テンプレート 【環境】OS, ブラウザをバージョンと共に記入してください。(ex: IE8, Firefox4) 【条件】期待する回答の条件を書いてください。(ex: jQuery不可, フレームワーク不可) 【何をしたのか】何をしたら問題の現象が発生するのか。再現手順を具体的に書いてください。 【エラーメッセージ】エラーメッセージがあれば正確に書き写してください。(Windows なら「コピット」を活用) 【期待する結果】最終的にどういう結果を望んでいるのか、を書いてください。 【サンプルコード】現象を再現可能な最小限のコードを書いてください。 1レスに収まらないならコード投稿サイトを利用してください。 http://jsdo.it/ http://jsbin.com/ http://jsfiddle.net/ http://ideone.com/ ■回答者へ ・回答には多様性があります。他人の回答を尊重してください ・動作ブラウザや環境が限られる場合は、それを明記してください ・他人の回答を批判する代わりに、自分ならこう書くという例を示してください ・質問者がJavaScriptでなければ実現できないと勘違いしてるなら、その否定としてHTMLとCSSで実装しても良い ・他人の回答を見たくないのであれば、文句をつける代わりにNGにして見えないようにしてください。文句をつける=荒らしです > 問題があれば捨てればいいだけでその時に例えば>>174 のような感じだと > 4個も公開変数があるから結局一部を捨てたりということもしづらい 公開変数ってなんや? this.foo なんてのが公開変数やろ? どうみても>>174 はローカル変数や 一部を捨てたりってなんや? 全くもって意味不明だ 初心者です。 この本(http://amzn.asia/386grG8 )を文中の課題をやりながら読み終わったので、 次はこちらの本(http://amzn.asia/cDn7CWG )に行こうと思っております。 この話を知人にしたところ、旧版(http://amzn.asia/cv1is9n )を持っているから貸してやろうか?と言われました。 同じ本ですが2010年の旧版です。 javaScriptの学習において そこまで問題がなければ旧版を借りようかと思うのですが、 この界隈の技術の移り変わりは早いので本書も最新版を買うべきでしょうか? 初めてのJavaScript 第3版、オライリー、2017 この本は、ES6(2015)の本だけど、 プログラミングを数年以上やっていないと、難しくて読めない 初心者は、(ECMA Script)ES3, ES5, ES6 と順番に、やった方が良いかも 今のブラウザは、ES5だけど、 ES6ではクラス構文などもできて、極端に難しくなる >>201 間違いなく新しい方が良いけど 古いから役に立たないって訳でもない クラス構文習うよりprototype習うほうが難しくね? >>174 , >>185 ありがとうございました! >>201 あってもいいけど物理的な本は必要か?と思う あるていど経験してるとサイト検索で十分だと思うけど 最初のうちは体系立てて勉強できるように、本がいいと思う >>204 プロトタイプは超簡単 「prototype」は難しいが、それはプロトタイプベースとは関係なく 関数をクラスに見立てたJSの旧クラスシステムで必要になるもので本質とは関係がない でもプロトタイプベースで書けるようになったのはES2015からで その教え方をしている入門書なりは見たことがない phpマニュアルみたいなサイトないもんかね あれを一度ガッツリ読むとすんげーレベルアップするんだけどな >>208 > でもプロトタイプベースで書けるようになったのはES2015からで JavaScriptは最初からプロトタイプベースだよ 「俺は昔のJavaScriptはプロトタイプベースとは認めん!」というのは無しな それはお前の「オレオレ定義」であって世間一般には通用しないものだから 世間一般にはJavaScriptは最初からプロトタイプベース HPで友達が稼げるようになった情報とか ⇒ http://asaswq3wq.sblo.jp/article/181819223.html 興味がある人だけ見てください。 717PZBPVIE >>210 いやいや、JSのベースがプロトタイプかどうかを言ってるんじゃなくて、 プロトタイプベースらしいプログラミングができる言語だったかを言ってるんだよ ES2015まではプロトタイプの設定が自由にできなかったんだが それでプロトタイプベースプログラミングが出来るわけ無いでしょ だから長らく継承テクニックとしてJSの内部プロトタイプの操作を利用するハックが使われてきたのよ それでもES2015でいうextendsの効果にもある 関数のプロトタイプを別の関数にするとかいう重要な操作はできなかったわけよ でも当時でも独自実装であった__proto__を使えばそれは容易にクリアできたわけで それこそがプロトタイプベースのポテンシャルなわけよ class構文追加でより難しくなるかどうかの話だったと思うが >>214 とりあえず自分が言いたいことは、prototypeプロパティやnew演算子を使った継承周りのテクニックは 確かに簡単とは言いにくく、class構文はその点分かりやすいけれど、 勘違いしてほしくないのは『プロトタイプ』を活用した継承システムは本来簡単なはずなんだってこと でもJSでは長らく活用が許されてなかったので、プロトタイプベースOOPの文化や学習が整っていないということ >>215 因みにプロトタイプベースらしい書き方ってどんな感じ? TypeScriptメインだからよくわからんのだ >>216 最初から用意されている1つのクラスシステムに縛られないのがプロトタイプベースの良さと言っても 大きなコードを書けば自ずと抽象化の結果として何らかのクラスシステムを作ることになる 既存のJSの2つのクラスシステムは当然内部的にプロトタイプベースのプロトタイプ設定を利用しているのを見ても分かるが プロトタイプの自由な設定機能がないとまともなクラスシステムを作るのは困難 一番わかり易い形で具体的に絶対にできないことを挙げるなら上で書いたように関数のプロトタイプ設定 つまり関数へのメソッドの継承が実現できない 因みにプロトタイプベースらしい書き方って言うのも一概には言えないのかもしれないし、 実際はコンストラクタ的な機能を考えたりしてクラスシステムを構築する場合もある そもそも自分がこれを挙げた理由は継承の概念を理解するのが簡単ということで 本当に単純なプロトタイプの設定だけでOOPが円滑にできるとは言わない その上で書くと class B { m() { return 6 } } class A extends B { m(){ return 7 * super.m() } } let o = new A o.m() というのと let B = { m() { return 6 } } let A = { __proto__: B, m(){ return 7 * super.m() } } let o = { __proto__: A } o.m() というの、初めて継承やらを理解する時にはオブジェクトだけで説明できる後者の方が仕組み理解し易くないか? 少なくとも、class構文でない旧クラスシステムで書いたコードと比べたら明らかにそうだよねってこと >>213 いや、だからそれはあんたの「オレオレ定義」であって 世間一般ではJavaScriptはプロトタイプベースのオブジェクト指向だって 最初から言われてる 言われているかどうか。事実の話をしている。 あんたが認めるかどうかじゃない >>218 俺は前者だな 知ってるからかもしれんが class構文がなかったころと比べたら まあどっちも理解しやすい >>217 > つまり関数へのメソッドの継承が実現できない それはクラスベースでは当たり前にある機能で プロトタイプベースはクラスベースと同じ機能が なければないと思ってるからだよね? つまりあんたはクラスベースとプロトタイプベースを 違うものだって考えられてないってこと プロトタイプベースをクラスベースの書き方を変えただけと思ってるから クラスベースと同じ機能がない=プロトタイプベースではない という意味がわからないことになってるんだよ。 ようするに「プロトタイプベースのオブジェクト指向」を やるのであれば昔のJavaScriptでもそれは普通にできる プロトタイプベースのオブジェクト指向で クラスベースの真似事をしようとするから 機能が足りないって思ってしまう プロトタイプベースでやるならば、 別に最初から機能は不足してない これも一応書いておくか 言いたいことはいろんな形のオブジェクト指向があるということ https://codezine.jp/article/detail/3708 > 継承は決してオブジェクト指向の必須技術ではありませんが > (実際、継承を持たないオブジェクト指向言語も存在しています)、 >>222 完全にJS流クラスシステムに毒されてんな 自分はプロトタイプベースのメリットは最初から用意されているクラスシステムに縛られないことって言ったでしょ? でも旧JSは半分、いや3/4くらい縛られてたわけよ 旧JSでプロトタイプベースっぽい、つまりクラスに縛られない固い言語でない特徴が現れていたのは オブジェクトとプロパティのゆるさだけで、ここで問題にしている継承周りに関しては 他のクラスベース言語同様に縛られていたし、むしろクラスシステムがクソな分状況が酷かった だからみんな旧クラスシステムの内部のプロトタイプ操作を利用する 『機能が十分なクラスシステム』をいろいろ考えてたわけじゃん それでも関数のプロトタイプ設定はできないってことが長年の悩みだったわけだけどね それと話を整理するけど プロトタイプベースでも機能は足りるっていうのは話が食い違っている よく考えてみて それって、new演算子やprototypeプロパティを使えば、 プロトタイプの設定ということができなくても継承は十分に実現できるって言いたいんでしょ? でもこちらはそもそもそのnew演算子やprototypeプロパティを使ったJS流旧クラスシステムの複雑さと 本来のプロトタイプベースでの継承実現の簡潔さを比較してるんだよ 話がおかしいよね? あとそちらこそプロトタイプベースとクラスシステムの関係を分かっていないようだけど プロトタイプベースでも、デフォルトのクラスシステムがあることとは矛盾しない それに縛られないってことが重要だからね > それって、new演算子やprototypeプロパティを使えば、 > プロトタイプの設定ということができなくても継承は十分に実現できるって言いたいんでしょ? いわんよ? 継承はオブジェクト指向に必須ではない。 new演算子やprototypeプロパティを使えば、 プロトタイプベースのオブジェクト指向が実現できる それだけ 分かった分かった、自分が悪かった 『継承』っていうのをクラスベース的な捉え方してクラス同士の話だけと思っている人がいるようだから話が食い違うんだな 自分が言っているのはプロトタイプ的継承だったり、もっと一般的な「継承」の話だから 例えば>>223 でも引用されているWikipediaを見てくれ https://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF_ (%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0) まさに序文に書かれている『あるオブジェクトが他のオブジェクトの特性を引き継ぐ場合』っていうのを指して言ってる だからnew演算子やprototypeプロパティだって継承のための機能なんだよ 要するに継承が云々言ってきたのは、(ある程度構造化した状態で)プロトタイプチェーンを繋げるのは云々って話だから スクリプト書こうとするとNGワードが出て書き込めない… 質問したいのに〜 var elmDiv = document.createElement('div'); var hoge = document.getElementsByClassName('test'); hoge[1].parentNode.insertBefore(elmDiv, hoge[1].nextSibling) ↑のようなスクリプトを書いて <div class="test"> <div class="test"> 【追加のDIV[1]】 <div class="test"> 【追加のDIV[2]】 <div class="test"> ↑のような形でDIVを複数追加したいのですが、書き方がわかりません; hoge[1]のみだと正しく追加されるのですが、hoge[2]を書くと上書きされてしまいます。。 任意の配列に複数要素を追加する書き方をご教授願えませんでしょうか…? >>226 まだ話が食い違ってるな。 俺が最終的に言いたいことは、JavaScriptは昔からプロトタイプベースの オブジェクト指向だってことだけだよ で君がいいたいことはだいたい分かる。 それに対して反論するならば、 [君がいいたいこと] 昔のJavaScriptは継承がやりにくい それは事実だろう。だがやりにくいからといってもできる以上 プロトタイプベースであることを否定することにはならない。 つまり継承がやりづらいプロトタイプベースのオブジェクト指向 [君がいいたいこと] 一般的な「継承」ができない(面倒) 大変でもできる。できるのだからオブジェクト指向と言える。 それにそもそも継承はオブジェクト指向の必須要件ですらない だからプロトタイプベースのオブジェクト指向 わかる? 継承があってもなくても、面倒であってもそうでなくても JavaScriptは昔からプロトタイプベースのオブジェクト指向なんだよ >>228 本当にNGワード?ブラウザで書き込めるんじゃない?って思わなくはないが、 jsfiddleあたりで動く最低限のサンプルコード書いてから質問すればいい あ、やっぱり動く最低限のサンプルコード書いてもらわないとダメだな divがネストしてるのかどうかわからんから答えられん 任意の配列とか言ってるのに、1以上から始まってるのが謎だし じゃあ複数とはいくつまでなのかとか書いてないし情報が足りんだよ まあ、情けでエスパーして(いつも通りjQueryで)書いてやったが 次はもれなく情報を書くか、jsfiddleにサンプル書くか、その両方をやってからレスしてくれ https://jsfiddle.net/ft3aegkx/ >>229 >上書き 上書きの意味がよくわからんが、 2回目の追加は、実際は1回目に追加した elmDiv の移動になった ということか? 追加するたびに createElement(cloneNodeでもOK)で 新たに要素を作成しないとそうなる 要素を2つ、追加したいのなら、 まず要素を2つ、作った(new した)かどうかを確かめる var aaa=undefined; とのか変数にundefinedを入れるって文法的に正しいのでしょうか? undefinedって変数未定義のときにwebコンソールとかで出ると 考えているため、変数に代入することはないと思ってんですけど どうなのでしょうか? 文法的には問題ない NaNとかと同じ ただ変数に直接入れるような使い方が相応しい場面はかなり少ないと思う undefined は、JS の実行環境が使うもの プログラマーが使うのは、null すいません、正規表現について教えてください メールアドレス判定の許可として下記条件にプラスして /^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/ 空(何も無い)も許可として追加したいのですが どのように書いたらよいでしょうか・・ /^(^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$)?$/ 出来なくもないけど非常に分かり辛い 文字列長0で分岐させたほうが良さそうな気がする >>240 正規表現をそのまま使うやつは馬鹿 名前をつけて使え 名前というのは関数名のことだ。 function is_email(email) { 正規表現チェック } 空を許可するんだろう? function is_email(email) { emailが空なら return true 正規表現チェック } こうすればよかろう 質問です 環境はvagrantでubuntu16.04を使用してます vue-cliを使ってるんですけどnpm run buildしてlocalhost:8080にアクセスできません。 ポートフォワーディングは8080→8080で設定しています。 http_proxyも設定しています。 ローカルホストからアクセスする方法を教えてください buttonをclockすると、現在値を取得し、 lat(緯度)、lng(経度)、distance(距離)をgetパラメータとして渡し、同じページに遷移したいと思っています ・lat(緯度)、lng(経度)はgetCurrentPositionの引数のfunctionから取得 ・distanceはbuttonタグの属性から取得。 例)<button data-distance="1000"> lat(緯度)、lng(経度)はは取得できましたが、distanceは取得できませんでした 何故でしょうか? $(function(){ $("button").click(function(){ navigator.geolocation.getCurrentPosition( function(pos){ var crd = pos.coords; var url = location.href; url = url.replace(/\?.*$/,""); window.location.href = url +'?lat='+ crd.latitude + '&lng=' + crd.longitude+ '&distance=' + $(this).data('distance'); }, function(){ console.log('error'); } ); }); }); >>247 高速回答ありがとうございます! もうちょっと考えてみます $(this).attr でええやろ dataはキャッシュかなんかですげー使いにくいぞ スコープの問題と分かりました こういう場合はどう解決すればいいんでしょうか? グローバル変数にする、DOMにclassをつける、などが思い浮かびましたが違う気がしてなりません お助け下さい・・・ $(function() { $('button').click(function() { var distance = $(this).data('distance'); navigator.geolocation.getCurrentPosition( function(pos) { var crd = pos.coords; var url = location.href.replace(/\?.*$/, ''); window.location.href = url +'?lat='+ crd.latitude + '&lng=' + crd.longitude+ '&distance=' + distance; }, function() { console.log('error'); } ); }); }); >>251 なるほどー!なるほど!ありがとうございます jsって難しいですね locationの部分、これでいいのかな? あまり$.paramって使わんのよね $(function() { $('button').click(function() { var distance = $(this).data('distance'); navigator.geolocation.getCurrentPosition( function(pos) { var crd = pos.coords; window.location.search = $.param({lat: crd.latitude, lng: crd.longitude, distance: distance}); }, function() { console.log('error'); } ); }); }); >>249 attr使うぐらいなら、<input type="hidden" name="distance" value="1000> だな なぜかって? GETのパラメータだからだよ 現在地の取得をどうにかできるならば、HTMLだけでこれで実行できるでしょ? <form> <input type="hidden" name="lat" value="?"> <input type="hidden" name="lng" value="?"> <input type="hidden" name="distance" value="1000"> <input type="submit"> </form> これにJavaScriptで現在地を入れ込むという処理を割り込ませると考える 例えばこんな感じ $(function() { $('form').on('click', ':submit', function(event) { var form = event.delegateTarget; event.preventDefault(); navigator.geolocation.getCurrentPosition( function(pos) { var crd = pos.coords; form.lat.value = crd.latitude; form.lng.value = crd.longitude; $(form).submit(); }, function() { console.log('error'); } ); }); }); コードを短く出来たわけじゃないけど HTMLだけで動くことを確認して、その続きで 処理を加えていくという作り方ができる 現在地の取得はhttpsにしないとエラーが出るゾ 気づいたら昔作ったサービスが動いてなかったゾ ここは、JavaScript のスレです Java ではありませんので、スレ違い! 動画サイトを見ていて、動画ページでコメントだけを見たいときとかに、ページを軽くしようとして $("video").remove(); とか $("video").parent().remove(); とかするのですが、これだと音声は再生されたままになってしまいます コントローラーは消えるので音声を止められないし、ミュートだとちょっと重くなりそうなので ムービー関係のもの全て消す方法ってないでしょうか? 例サイトはYouTubeです >>261 pause() を使うとか、src属性を無効なURLに設定するとか >>261 for (var video of document.querySelectorAll('video')) { video.pause(); video.parentNode.removeChild(video); } >>262 ,264 再生を止めても、裏では動画や音声は読み込まれてるので、やっぱり結構CPUメモリ食べちゃうんですよね >>263 無効なURLにするの良さげですね ありがとうございます >>261 一時期軽くしたいと思っていたときは、 そういったものは原則OFFで、必要なときだけ再生するようにしていたな 昔はProximitronでHTMLを書き換えて実現していた、 比較的最近はブラウザの機能でFlashを自動的に再生しないようにしていた もしかしたらブラウザに動画を自動的に再生しないような 設定があるんじゃないかな? もし今の俺が同じことをやろうとしたら、ブラウザのプラグインである TampermonkeyかStylishを使うかな? 実現できるか知らんけど おみとろん懐かしいな 今ならTampermonkeyだろうけど 本気でコメントだけ読みたいならapiを叩くという手もある EcmaScriptという言葉はES5あたりから良く聞くようになったと思いますが それより前のES3相当のJavaScriptも、 EcmaScriptの標準を参照して作られていたのでしょうか? https://developer.mozilla.org/ja/docs/Web/JavaScript/Language_Resources ECMAScript は JavaScript の基礎を成すスクリプト言語です。 ECMAScript は標準化団体 ECMA International によって ECMA-262 および ECMA-402 specifications として標準化されています。 次のような ECMAScript 標準が承認済みおよび策定中です: ショッピングサイトにビットコイン決済を導入した際に、価格表記をビットコイン、マウスを重ねたら円表記が出るシステムを外注したいのですが、JavaScriptで大丈夫でしょうか? >>272 できるよ マウスオーバーで表示変わるのはJavaScriptの得意とするところだから問題ない 単純なのならCSSでもできる リアルタイムな相場の取得はAPIでできる 仮想通貨の各取引所がAPIを公開してるからそれ使えばいい 取引所によって取得の仕方や形式が違うからその辺は好みかな ずっと提供されるかは保証ないからいくつかをフェイルオーバー的に作っておいた方がいい >>273 事細かにありがとうございます。 プログラミングの知識はないのですが、外注に当たって方向性だけでも確認したかったので助かりました HTMLは初級ぐらいでJavaScript(TypeScript)も普通ぐらいには使えるようになって、 Reactも使えるようになったのですが、目的のUI作れません。 WPF/UWPならXAMLとコントロール使って、AndroidならレイアウトファイルとViewコントロールを使って 複雑でないUIならとりあえず普通に作ってアプリ作れるんですが。 自分のレベルだとWebアプリだとかなり死ねます。 例えば、ちょっとこの項目を右寄せ表示するにしてもできねぇーとかのレベルです。 やっぱ、CSSを覚えるしかないのでしょうか??みなさんはバリバリCSS使いこなしてるんでしょうか?? >>275 の続きです。 例えば、Material UIなどReact用のコンポーネントはドキュメント見れば普通には使えるようになったんですが、 タブにアイコンつけたいとか、リスト表示でこの項目を右寄せしたいとか Reactコンポーネントのプロパティに用意されてないことやると、 とたんにダメなレベルで、UIがつくれません。 >>275-276 cssも覚えないと、結局細かい事は何も出来ない >タブにアイコンつけたい font-awesomeのver4を使う >リスト表示でこの項目を右寄せ text-align:right >>275 > やっぱ、CSSを覚えるしかないのでしょうか??みなさんはバリバリCSS使いこなしてるんでしょうか?? HTMLもCSSも使いこなしてるよ。というかJavaScriptだけでやろうとしたら破綻する 基本的にJavaScriptではデザインは作らない JavaScriptでやるのは状態に応じてclassを設定するとかそういうことぐらい そのclassに応じてどういう見た目にするかはすべてCSSで行う そうしないと面倒なだけだから 逆にCSSを使いこなすと処理とデザインの責任範囲が明確になるから コードはシンプルになるし、デザインの修正も簡単になる 個人的には細かいこと気になるならCanvasの方がオススメ >>234 >>235 >>236 規制で書き込めなかったけど読ませていただきました。 無事解決しました!ありがとうございました(遅) 「当方のエージェントは、追跡を避けるためメールアドレスを毎週変更している。 かあわいい ついに宇宙一難解なパズルが完成しました・・ その名も 『宇宙一難解なパズルゲーム』!! http://jagarikin.html.xdomain.jp/pzl.html htmlでできてるのでブラウザから手軽に宇宙一難解なパズルをプレイできるよ〜 5年ぶりに触り始めたんですけども、 var不要論ってなんすかね? let, constが使えるならvarで宣言する意味はない(少なくともletに置き換えて問題ない) そして現状、メジャーな環境では使える それならvarいらんよね、という主張かと コールバックの中のreturnについてお伺いします。 ttps://azu.github.io/promises-book/#promises-overview の中の、promise-workflow.jsについてなのですが、 このサンプルコードを仮に2連続で呼び出すように改変する場合、A部分を asyncFunction() .then(function (value) { console.log(value); // => 'Async Hello world' return asyncFunction() }).then(function (value) { console.log(value); // => 'Async Hello world' }) のように書くかと思うのですが、最初のthenの中の、 return asyncFunction()のreturnは、関数を実行するだけなのになぜ必要なのでしょうか? 以前も別件でfoo.map( ( x ) => x*2 )を foo.map( ( x ) => { x*2 } )と書いてしまい、returnでハマりました。 どなたかこのreturnのミステリーについて教えてください。 >>287 > 関数を実行するだけ ではない。 asyncFunction() は promise も返す。 2 つめの then は、その promise がresolveされたときに呼ばれることになる >>288 訂正 2 つめの then は、… → 2 つめの then の中のfunctionは、 … >>289 ありがとうございます。 asyncFunction() .then(function (value) { console.log(value); // => 'Async Hello world' asyncFunction() }).then(function (value) { console.log(value); // => 'Async Hello world' }) この書き方では動かないのは、これではpromiseが返ってこないということです…かね? 説明が下手で本当に申し訳ないです。 Promiseのthenメソッドが返すPromise Tはthenメソッド中でPromise Rを返した場合 Rの解決を待って、その解決値を持ってTが解決されることになる つまり実質的にT==Rと言うように振る舞わせることが出来る つまり、 非同期A .then( Aの解決値を得て、別の非同期Bを実行 ) .then( Bの解決値を得て、別の非同期Cを実行 ) .then ...... というようにどんどんthenを繋げて行くことができる 勿論then中でそのチェーンとは独立したPromiseを作成することを繰り返してもいいが、 そうすると所謂コールバック地獄のようにネストが深くなってしまう それを平坦化するためにこの機能がある >>290 Promiseをreturnするのが自然だけど 気持ち悪いなら別にこう書いたって良い https://jsfiddle.net/4kks4bns/ 皆さん、ありがとうございました。 ようやく納得がいきました。 この流れで理解できたのか・・・? なんか質問者も回答者もずれまくってる気がするんだが なぜか納得してるようだが、これで納得できるはずがないので勝手に説明するわ まず基本(?)系。thenを二回続けているが、asyncFunction()は 一回しか読んでないパターン asyncFunction() .then(function (value) { console.log(value); // => 'Async Hello world' ・・・(1) }).then(function (value) { console.log(value); // => undefined ・・・(2) }); (2)でundefinedになっているのは、1回目のthenで何もreturnしてないから JavaScriptは関数で何もreturnしてない場合はundefiendになる (Rubyなどのように最後に評価された値ではない) 次のように、thenでreturnすれば次のthenの関数の引数に渡すことができる asyncFunction() .then(function (value) { console.log(value); // => 'Async Hello world' ・・・(1) return value; }).then(function (value) { console.log(value); // => 'Async Hello world' ・・・(2) return value; }); >>297 の例では、return valueと単なる値を返した、 単なる値を返すと、次のthenの引数になるが、 単なる値の代わりにPromiseオブジェクトを返すこともできる function newPromise() { return new Promise(function (resolve, reject) { resolve('new-promise'); }); } asyncFunction() .then(function (value) { console.log(value); // => 'Async Hello world' ・・・(1) return newPromise(); // 参考 return Promise.resolve('new-promise') と書いても良い }).then(function (value) { console.log(value); // => new-promise' ・・・(2) return value; }); この場合、2番目のthenの関数の引数には、Promiseオブジェクトが渡されるのではなく、 Promiseでresolveされた値(new-promise)が渡される もしnewPromiseがresolveするまでに時間がかかる場合は、 2番目のthenが呼び出されるまで時間がかかるということ thenで単なる値を返した場合は、次のthenはすぐに実行される。 すぐにresolveされたのと同じだと考えればいい このように、thenでreturnするのは単なる値でもPromiseオブジェクトでも良いという 仕様のために、Promiseを返さない単なる関数をあとからPromiseに変えても 同じように動かすことができる。同期と非同期の違いを吸収していると考えることができる。 >>287 でreturnしない場合、 asyncFunction() ・・・(a) .then(function (value) { console.log(value); // => 'Async Hello world' ・・・(1) asyncFunction() ・・・(b) }).then(function (value) { console.log(value); // => undefined ・・・(2) }) (a)のasyncFunction()につながってるthenの結果として (1)と(2)のconsole.logが実行される。 (2)のconsole.logがundefinedなのは間違いではない。 なぜならthenでreturnしてないのだから当然undefinedになる (b)のasyncFunction()は何の意味も持たない。なぜなら(b)がresolveしても その後にthenがないので(b)の結果としては何も出力しない returnした場合は意味が異なる。(a)の1番目のthenの戻り値はPromiseオブジェクト そのため(b)がresolve()された後にresolve()された結果が2番めのthenに渡される。 asyncFunction() ・・・(a) .then(function (value) { console.log(value); // => 'Async Hello world' ・・・(1) return asyncFunction() ・・・(b) }).then(function (value) { console.log(value); // => 'Async Hello world' ・・・(2) }) 注意として(1)のvalueと(2)のvalueは(同じ文字列だが)違うオブジェクト (1)は(a)がresolve()された結果だが、(2)は(b)がresolve()された結果 >>287 の > 以前も別件でfoo.map( ( x ) => x*2 )を > foo.map( ( x ) => { x*2 } )と書いてしまい、returnでハマりました。 これは単純な勘違いをしているだけ { } を省略したら return も省略できる { } で囲んだら return が必須 というだけの話 個人的にはアロー関数は、関数っぽく見えないのも利点の一つだと思ってるので 前者の書き方をおすすめする。 { } をつけて returnを書いて、ましてや { } の中に 複数の式や文を書くのはなんか違うと思ってる ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる