+ JavaScript の質問用スレッド vol.130 + [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
JavaScript を自ら学ぶ人のための質問スレッドです。
>>2-6のテンプレを読んだ上で質問してください。次スレは>>950が>>2のテンプレ案(本スレで改善案があれば考慮)を元に立ててください
■規則/推奨ルール
・メール欄を空欄にし、名前にレス番を入れることを強く推奨(なりすまし防止)
・質問内容は具体的に。言葉だけでなく、出来る限り再現性を確認したサンプルコードの掲示。
・質問テンプレートの利用推奨。
・質問への「答え」だけでなく「意見」を出しても良い。
■禁止行為
・丸投げ質問
・迷惑スクリプトの質問
・オレオレ用語の使用(一般的な用語を使用する事)
・煽り、批判等の他人を不快にさせる行為(批判の代わりに「AよりBが良い」のような代案を出す事)
・回答者同士のレスは原則禁止(>>6を参照)
・ライブラリの話題の投稿(>>6を参照)
■質問テンプレート
【環境】OS, ブラウザをバージョンと共に記入してください。(ex: IE8, Firefox4)
【何をしたのか】何をしたら問題の現象が発生するのか。再現手順を具体的に書いてください。
【エラーメッセージ】エラーメッセージがあれば正確に書き写してください。(Windows なら「コピット」を活用)
【期待する結果】最終的にどういう結果を望んでいるのか、を書いてください。
【サンプルコード】現象を再現可能な最小限のコードを書いてください。
1レスに収まらないならコード投稿サイトを利用してください。
http://jsdo.it/ http://jsbin.com/ http://jsfiddle.net/ http://ideone.com/ Object.getOwnPropertyDescriptor( window, 'undefined' )
// { value: undefined, writable: false, enumerable: false, configurable: false } >>427
undefinedの上書きができなくなったことがどう関係するんだ?
undefinedの上書きができれば、属性の有無を調べるメソッドが
無くてもいいってことだろ? in演算子なんてあったんですね
ありがとうございます 画面構成が一貫したSingle Page Applicationを作っていました
ベースとなるHTMLは最初から記述されていて、
適宜要素を動的に操作していたのですが
異なる構成の画面が必要になりました
部分的な書き換えではおさまりません
そうなると最初の画面から完全に動的に書かなくてはいけないのか?
それとも今の画面をどこかに保存しておいて、処理が終わったらまた戻す?
とか色々考えていますが
こういうことが問題になったらそろそろフレームワークの導入を考えた方がいいのでしょうか? >>431
hasOwnProperty と使い分けよう >>432
スケールしないことを実感したら切り替え時だろう >>432
もう1個 別のSPA 作って
ShareWorker で状態を共有させる方法もあるんじゃないかな chromeとIEで確認しています
下記のような形でクリックイベントリスナーを設定しましたが反応はありませんでした
どこに問題がありますでしょうか?よろしくお願いします
Hoge.prototype.foo = function(){
var button = document.createElement( "input" );
button.type = "button";
button.value = "テスト";
button.addEventListener( "click", this.bar, false );
this.div.appendChild( button );
}
Hoge.prototype.bar = function(){
alert( "click" );
}; >>437
要素が生成されていないのにイベントを与えているから >>437
途中で送信しちゃったw
this.bar
って第二引数に与えると、実際にクリックイベントが発火したとき
thisになるのはevent.targetであってHogeインスタンスじゃない >>440
試しに下記の様にしましたが変わりませんでした
this.div.appendChild( button );
var func = this.bar;
button.addEventListener( "click", func, false ); >>441
変わってないよ
var A = this;
button.addEventListener('click' , function(){ A.bar(); } , false);
とか
これがベストとは言わんけど >>441
そのやり方でもthisになるのはevent.targetであってHogeインスタンスじゃない Function.prototype.bind() を使う Hoge.prototype.foo = function(){
this.div.appendChild(button);
button.addEventListener( "click", function(){
console.log( "test" );
alert( "test" );
},false );
}
そもそも発火しませんでした・・・ >>445
そんな中途半端に書かれてもわからんよ
this.divってなんぞや?とかとか
全部書いておくれ
https://jsfiddle.net/ 詳しいサンプルをありがとうございます
一旦最小構成でテストしてみたら最初のままで通用してしまいました
var Hoge = function( elementId ){
this.div = document.getElementById( elementId );
};
Hoge.prototype.foo = function(){
var button = document.createElement( "input" );
button.type = "button";
button.value = "ボタン";
this.div.appendChild( button );
button.addEventListener( "click", this.bar( this ), false );
};
Hoge.prototype.bar = function( arg ){
console.log( "arg is..." ); //
console.log( arg ); // object
};
var hoge = new Hoge( "test" ); // <div id="test"></div>
hoge.foo(); >>448
>button.addEventListener( "click", this.bar( this ), false );
これは間違ってるよ
第二引数に渡すのは関数
this.bar ← これは関数
this.bar(this) ← これは関数barを実行した返り値 訂正!訂正します
先の書き方だと第2引数が意図せずに実行されてるだけで本当は下記の通りですね
button.addEventListener( "click", function(){ this.bar( this ); }, false );
// this.bar is not a function at HTMLInputElement. >>450
>button.addEventListener( "click", function(){ this.bar( this ); }, false );
おちつけw
そのthis.barのthisは第二引数に渡した無名関数のスコープで
無名関数の外、つまりHogeのものじゃない
んでお手軽に解決するなら、Hogeのthisをいっぺん保存してこう
var A = this;
button.addEventListener( "click", function(){ A.bar( this ); }, false );
もっと根本的に解決するなら
Function.prototype.bind()
Function.prototype.call()
Function.prototype.apply()
あたりをググると良いよ >>451
その後色んなパターンを実践していましたが
最終的には、まさに一度thisを保存する方法に落ち着きました
(関数先でクラスのプロパティを参照する必要があるので)
スコープとbind()について落ち着いて調べてみたいと思います
みなさんありがとうございました JavaScript の、this は、コロコロ変わるから難しい。
bind を使わないと、拘束できない
jQuery を使えば、悩むこともない >>453
jQueryを使ってもそこは一緒
だけどjQueryだとクロージャーを使っても循環参照になりづらいのと
DOM要素のリストとして扱うという設計思想によって扱いやすいってだけ
でさ、お前ら何やってんの?
>>437の話だろ? なんでthisを保存とかいう話になってんの?
addEventListenerの第二引数にクロージャーなんか渡すから
話ややこしくなってるじゃん。 >>437のコードでだいたいあってるだろ
https://jsfiddle.net/rdeuvep2/
function Hoge(elementId) {
this.div = document.getElementById(elementId)
}
Hoge.prototype.foo = function() {
var button = document.createElement( "input" );
button.type = "button";
button.value = "テスト";
button.addEventListener( "click", this.bar, false );
this.div.appendChild( button );
}
Hoge.prototype.bar = function() {
alert( "click" );
};
var hoge = new Hoge("buttons");
hoge.foo(); んで、恒例のjQuery化w
なるべく元の形を保ったバージョン
https://jsfiddle.net/rdeuvep2/1/
function Hoge(elementId) {
this.elementId = elementId
}
Hoge.prototype.foo = function(){
$("<input>", {type: "button", value: "テスト"}).click(this.bar).appendTo(this.elementId)
}
Hoge.prototype.bar = function(){
alert( "click" );
};
var hoge = new Hoge("#buttons");
hoge.foo()
俺はHogeクラスなんか作らずこんなんでいいと思ってる
https://jsfiddle.net/rdeuvep2/2/
var attrs = [{value: "テスト1"}, {value: "テスト2"}];
var buttons = attrs.map(attr => $("<input>", attr).attr({type: 'button'}));
$("#buttons").append(buttons).on('click', 'input[type="button"]', function() {
alert( "click " + this.value);
});
>>455
アロー関数使ってやったぜ?w classを使って書いたバージョン
https://jsfiddle.net/rdeuvep2/3/
>>455
アロー関数つかってやったが、
>>454で書いたとおり、今回はアロー関数もクロージャーもいらない 補足
「今回は」アロー関数もクロージャーもいらない
今回の要件にthisがどうなるかってのが書かれていないから
this.barは今回は動くがthisは違っていると念の為に言っておく
いろんなサンプル追加
https://jsfiddle.net/rdeuvep2/6/ qiitaで記事うpしても叩かれない知識を身に着けたいんですが
JavaScriptという言語を学ぶための良書を教えてください その考え方は大間違い
人に意見を発信する以上は文句を付けられて当たり前
そしてそれは良いこと
お互い内外から叩き合ってきれいな球に近づくのだから
それを防ごうと言うのはトゲトゲボールか、スライムになってしまうのがオチ >>459
とりあえずサイ本
現段階のおまえさんのレベルも
おまえさんが書いた記事にツッコミを入れる奴のレベルもわからんから
それを数冊の本でなんとかするのは難しかろう JavaScript 第6版、2012、David Flanagan
Google などのプロの机に、必ず置いてある本 プロのJSerやWEBエンジニアならオンライン仕様書以外は必要ない
そういうのはJSの常識を知らない非JSネイティブプログラマ向けに用意されてる
それもES2015以降の今の時代に於いては、JSを歴史から学んでJS仙人を目指したい人以外には過去の有名な本という飾りでしかない 初心者はまずはMDN 「MDN ○○」でググる
そしてより詳しく知りたければMDNの各記事の下に仕様へのリンクが張ってある
徐々にそっちに移行していく let lastTimeSignal;
setInterval(fuction(){
let now = moment();
let nowMinutes = now.format('YYYYMMDDHHmm');
if (now.minutes()==0 && lastTimeSignal !== nowMinutes){
lastTimeSignal = nowMinutes;
/*処理*/
}
},1000);
みたいなコードがあります
moment()はmoment.jsです
現在時刻の分数が0の時に一度だけ実行する、ようは時報です
ですが、ごくまれに連続して複数回時報が実行されてしまうことがあります
lastTimeSignalが設定されるので排他的に処理されるはずなのに
何故複数回実行されてしまうのか分かりません
現象はchromeで確認しています
lastTimeSignal とnowMinutesをログに出力するようにしましたが
連続実行された時の値は全く同一でした
lastTimeSignalが設定されないまま
複数のインターバルが呼び出されている、としか思えません
処理は、何かと不安定なSpeechSynthesisUtteranceを使っているので
それが原因なのかとも思いますが
処理の前にlastTimeSignal = nowMinutesとすぐに代入しているので、
たとえSpeechSynthesisUtteranceに問題があっても排他処理まで失敗するのは奇妙です
関数の外の変数(lastTimeSignal)への変更が
すぐに反映しない、なんてことあり得ますか? >>468
あらためてログを確認すると
10/13 05:00:00.97
10/13 05:00:00.98
と、0.01秒差で連続実行されていました
1秒ごとに実行されるはずのインターバル処理が、
ほぼ同時に2回呼び出されていることになります
一体何故・・?
いま、ふと思い付いたのですが
不安定なSpeechSynthesisUtteranceの実行に更にsetTimeoutを挟めば
変数の変更まで不安定になることは防げるかもしれません とにかく問題が再現できる最小限のコードを貼りなさい
できればライブラリも除いた状態で
まずそうやって削ぎ落としていくのがデバッグの基本でもある ここに質問するくらいならteratail使えや。コード見づらい。 明確な根拠もなく実行系を疑うのはプログラマ憲法でタブーとされていること 恥ずかしいことに、インターバルタイマーを複数回設定していたのが原因でした
ライブラリの中の、
起動時にしか実行されないと思っていたハンドラの中で設定していたのですが
そのハンドラはその後の操作によっては複数回呼び出されるものだったのです
プログラマー憲法を心に銘じます
ありがとうございました まあでも非同期が絡むとデバッグが一段と難しくなるのは事実
ただコールバックで闇雲に投げて闇雲に呼ばれるのではなく
Promise,async-await,async generator辺りを適切に使って
シーケンシャルに管理すれば軽減できはする jsだと無名関数にしてしまう分、普通に何回も呼び出してしまうよな
アクセス解析の値がぶっとんでた時はあせったわ 無名関数だからって理由でそんなことすることはないな。
だって名前つけても同じ話だもの 無名関数ならそこでしか使わないんだから
逆に予定外に何度も呼び出すことなんて少ないと思うが ES2015でforEachがオブジェクトに追加されなかったのは何故ですか?
最近のJSはイケてると思っていましたが
いまだにオブジェクトをforEachできないのは違和感があります
もうかなり以前からunderscoreやlodashがforEachの有用性を証明してますよね >>480
だからlodashを使えばいいだけだろう? mapは新しい配列を作るためのものなので用途が違います
ライブラリは言語にあるべき未来を見せるのが役割の一つなので
それを何年も前に見せられてなおかつ放置してるのは怠慢と言わざるを得ません いや、ライブラリは言語仕様をシンプルにするのが目的だよ。
どんな言語でも言語自体に色んな機能を含めず
多くの機能はライブラリで提供されてるはずだ。 >>483
Mapと書くべきだったか
まあ意図は違うんだろうけど Mapじゃなくて地図と書くべき。
でないと、SMAPと勘違いされる可能性がある。 あの文脈ならMapで通じると思うけど
つーかもうオブジェクトからイテレーター作れるじゃん mapメソッドとは別にMapオブジェクトというのがあったのですね
イテラブルではない普通のオブジェクトを回すのはあまり行儀が良くない、
という判断が根底にあるのでしょうか?
でも
(new Map([['taro','name'],[15,'age']])).forEach((key,value)=>{
});
こんな書き方がイケてるとはあまり思えないのですが・・
newを書かずにMapオブジェクトを生成する
シンタックスシュガーを用意して欲しいところです >>488
シンタックスシュガーはいらないですね。
関数を用意すればいいだけですよ。 >>488
Object.entries(obj).forEach(([key,value])=>{}) >>490
これはなかなかいいですね
オブジェクトのインスタンスメソッドで出来て欲しいですが、
keyとvalueだけでなくindexも取れるところもイケてると思います >>491
そのやり方は列挙順を保証出来ないから、順序がランダムで良いときしか使えない
もともと、オブジェクトのキーは列挙する事を想定したものでもないし、連祖配列的なものを望むなら、足りない機能が多くて苦労すると思うよ たしかにオブジェクトのメンバに順序は期待出来ないですが
ループの中でループカウンタが欲しくなることはわりとあるので、
そういう意味です 未だにES5脳な奴がいるんだな
列挙の順序が保証されてないのはfor-in文とES5のObject.keys()
ES2015以降のObject.{keys,values.entries}()は保証されている
こんなんJSerなら誰でも知ってる常識だろう >>495
矛盾してるぞ
> こんなんJSerなら誰でも知ってる常識だろう
ES5脳なJSerは知らないだろ? JSは日進月歩なんだから
未だにES5脳な奴がJSerなわけ無いだろ JSerの定義でもめるぐらいなら、ES5erとES2015erに分けろ
JavaScript===ECMAScript2015ではないんだぞ async-awaitで逐次処理書いてる時に比較的長いタスクをやらせると
裏で動いているのかどうか分かんなくなるんですが。
定期的にconsole.logとかでログ出力していれば分かるんですが、
そうでない場合、逐次処理が実行中だってどうやって把握すればいいんですかね? そりゃconsole.logを適切な個数置くしか無いよ
それかメイン関数以外にあちこち置くのが嫌なら
await longTimeTask()
をpromiseが解決するまで一秒ごとにログを出すperiodicLogingを用意して
await periodicLoging( 'タスクA', longTimeTask() )
と書くとか、同様にしてタイムアウトさせたりするとか 結局時間かかるのはIOかEvent待ちのネイティブの部分だからステップ処理は意味ない。 結局時間かかるのはIOかEvent待ちのネイティブの部分だからステップ処理は意味ない。 >>502
>>499の目的である「動作確認」は可能だと思うが、どういう理屈で意味がない? そもそも確認したい動機が分からん
エラーハンドリングをあえてすっぽかしてない限り
棄却が伝わってこないと言うことは正常動作中ということで心配する必要ないだろう
パッチ処理とかで本当に10分とかかかるものなら
大本にProgressイベントが用意されていないのなら>>500のような感じになるだろうな str='黄と黄緑と緑'
.replace(/黄緑/g, '<span style="color:greenyellow">$&<\/span>')
.replace(/黄/g, '<span style="color:yellow">$&<\/span>')
.replace(/緑/g, '<span style="color:green">$&<\/span>')
黄緑にも色を付ける方法を教えて下さい >>507
その種の複数置換は結局
replace(/[黄緑]+/g, function(match){ … })
が簡単 >>508 でmatchで条件分岐がおすすめだけど超簡単にするなら「黄緑」を一旦「青」とかにしてから最後に戻すとかでもいいよ
ほほえましくてよきよき >>507
str='黄と黄緑と緑'
.replace(/黄緑/g, '<span style="color:greenyellow">$&<\/span>')
.replace(/黄[^緑]/g, '<span style="color:yellow">$&<\/span>')
.replace(/[^黄]緑/g, '<span style="color:green">$&<\/span>')
>>508-510
正規表現ぐらいもうちょい頑張れwwwww
ぐぐりながらやってみたけど30分でできたぞwwwww
>>511
最悪の回答wwwwww >>514
だからほほえましくていいって書いたんだけどw >>514
あ、一旦「青」にするってのが、よくわからずやってた頃を思い出してほほえましくていいって意味です >>512
どう見ても>>508の足元にも及ばない 間違えてるのか?正常に動いてるように見える
正規表現ほとんど使わないからわからんわ [^緑] は「緑以外の1文字」だから /黄[^緑]/ だと「黄と」がヒットする
/[^黄]緑/ も同じ
なので結果は
<span style="color:yellow">黄と</span><span style="color:greenyellow">黄緑</span><span style="color:green">と緑</span>
ってなるはず jqueryでは
セレクタに要素を複数並べて要素の子孫の要素を選択することが出来ますが
このように要素を選択する方法は何というのでしょうか? >>521
しかも文頭の緑と文末の黄にはマッチしないしな
ECMAScriptだと後読み出来たっけか >>506
おー。ありがとうございます
Progressイベントなんてあるんですね。
独自の処理にもそう言うの用意できるんですかね。 自前でonProgressプロパティに関数があれば呼び出してもいいし
EventEmitterみたいなモジュール使ってもいいし
DOMのカスタムイベント使ってもいいし >>524
後読みはES2018になりそう
現在モダンブラウザは要フラグ
>>525
async-awaitと組み合わせるのは工夫がいるよ
できればasync-generatorを使ってトランスパイルする ■ このスレッドは過去ログ倉庫に格納されています