私的良スレ書庫
不明な単語は2ch用語を / 要望・削除依頼は掲示板へ。不適切な画像報告もこちらへどうぞ。 / 管理情報はtwitterでログインするとレス評価できます。 登録ユーザには一部の画像が表示されますので、問題のある画像や記述を含むレスに「禁」ボタンを押してください。
元スレ+ JavaScript の質問用スレッド vol.122 +
JavaScript スレッド一覧へ / JavaScript とは? / 携帯版 / dat(gz)で取得 / トップメニューみんなの評価 :
レスフィルター : (試験中)
>>639
>>553を読めばわかる
> としとけばいいんでない
普通はやる必要がないこと。
removeEventListenerをするためには、名前を付けないといけない。
せっかくクロージャーを使って無名関数で
イベントハンドラを記述できるというのに、それは
newしたものを必ずdeleteしなければならない言語の
ようなもの。面倒くさい
> 一度しか実行されないハンドラは少数に限られるだろうから
それが昔のIEはページを移動してもメモリは解放されなかった。
だからどんどんブラウザが重くなっていった。
jQueryを使った場合は、クロージャーを使って本来あるべき姿のように
簡単に記述できていながら、メモリリークもしないようになっていた。
>>553を読めばわかる
> としとけばいいんでない
普通はやる必要がないこと。
removeEventListenerをするためには、名前を付けないといけない。
せっかくクロージャーを使って無名関数で
イベントハンドラを記述できるというのに、それは
newしたものを必ずdeleteしなければならない言語の
ようなもの。面倒くさい
> 一度しか実行されないハンドラは少数に限られるだろうから
それが昔のIEはページを移動してもメモリは解放されなかった。
だからどんどんブラウザが重くなっていった。
jQueryを使った場合は、クロージャーを使って本来あるべき姿のように
簡単に記述できていながら、メモリリークもしないようになっていた。
>>641
> クロージャを少なくする設計には賛成だが、循環参照は関係ない
クロージャを少なくする設計なんて考えていたら、
全然問題がないEcmaScriptのmapやforEach、
underscoreやlodashの関数まで
クロージャー使わないほうがいいって勘違いするぞ。
問題は生存期間が長いイベントハンドラでクロージャーを使うと、
それが呼び出されたのと同じスコープの変数も使わないものであっても
生き残ってしまうっていうのが問題だろ。
だから逆にそのスコープ内の変数の方をなくしてもいい。
> クロージャを少なくする設計には賛成だが、循環参照は関係ない
クロージャを少なくする設計なんて考えていたら、
全然問題がないEcmaScriptのmapやforEach、
underscoreやlodashの関数まで
クロージャー使わないほうがいいって勘違いするぞ。
問題は生存期間が長いイベントハンドラでクロージャーを使うと、
それが呼び出されたのと同じスコープの変数も使わないものであっても
生き残ってしまうっていうのが問題だろ。
だから逆にそのスコープ内の変数の方をなくしてもいい。
>>654
要するに循環参照しない
要するに循環参照しない
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', function() { });
}
↑これを ↓こう書けばいいことは分かった
function onload() {
}
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', onload);
}
巨大な配列は、onloadの中で参照しないからいいけど、
だけどonloadの中で参照したい変数があった時はどうするの?
つまり
function foo(value) {
var a = [巨大な配列]; // これは要らないけど
var b = value; // これは必要
window.addEventHandler('load', onload);
}
function onload() {
// ここでbを参照したい
}
クロージャーはこういうことが簡単にできるから
便利というめんもあるんだが
var a = [巨大な配列];
window.addEventHandler('load', function() { });
}
↑これを ↓こう書けばいいことは分かった
function onload() {
}
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', onload);
}
巨大な配列は、onloadの中で参照しないからいいけど、
だけどonloadの中で参照したい変数があった時はどうするの?
つまり
function foo(value) {
var a = [巨大な配列]; // これは要らないけど
var b = value; // これは必要
window.addEventHandler('load', onload);
}
function onload() {
// ここでbを参照したい
}
クロージャーはこういうことが簡単にできるから
便利というめんもあるんだが
>>656
jQueryを使えば簡単に実現できるよ。
jQueryなら追加のデータをイベントハンドラに渡せる。
その場合ならこのように書くことが出来る。
function foo(value) {
var a = [巨大な配列]; // これは要らないけど
var b = value; // これは必要
$(window).on('load', {b: b}, onload);
}
function onload(event) {
// ここでbを参照したい
console.log(event.data.b);
}
jQueryを使えば簡単に実現できるよ。
jQueryなら追加のデータをイベントハンドラに渡せる。
その場合ならこのように書くことが出来る。
function foo(value) {
var a = [巨大な配列]; // これは要らないけど
var b = value; // これは必要
$(window).on('load', {b: b}, onload);
}
function onload(event) {
// ここでbを参照したい
console.log(event.data.b);
}
>>657
バッチリです。やっぱりjQuery便利やね
バッチリです。やっぱりjQuery便利やね
>>655
循環参照はあまり関係ない
循環参照はあまり関係ない
この話を聞くと、Javaのクロージャーもどき(ラムダ)の
仕様は正解だったかもしれんな。
JavaScriptやいろんな言語のクロージャーはクロージャーの中から
aが見えてしまう。つまりイベントハンドラが生きてる間中、
イベントハンドラからaを参照しなくても、aが生き残ってしまう。
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', function() {
// ここからaが見える
});
}
でも、javaのラムダは、aが見えない。
それがラムダはクロージャーではないと言われる理由なんだが、
ラムダであればクロージャーを使った場合のこの問題が無くなる。
クロージャーはあってもいいと思うんだけど
クロージャーとラムダの両方がほしい。そして必要ないならば
ラムダの方を使うべきだろう。
仕様は正解だったかもしれんな。
JavaScriptやいろんな言語のクロージャーはクロージャーの中から
aが見えてしまう。つまりイベントハンドラが生きてる間中、
イベントハンドラからaを参照しなくても、aが生き残ってしまう。
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', function() {
// ここからaが見える
});
}
でも、javaのラムダは、aが見えない。
それがラムダはクロージャーではないと言われる理由なんだが、
ラムダであればクロージャーを使った場合のこの問題が無くなる。
クロージャーはあってもいいと思うんだけど
クロージャーとラムダの両方がほしい。そして必要ないならば
ラムダの方を使うべきだろう。
>>661
そうだね。
(DOMとJavaScriptの)循環参照はメモリリークを招くという
古いIEのバグに関連する話で、
それを除けば循環参照してもよい。
ただ循環参照とハンドラの生存期間が長い問題は別の話で
ハンドラにクロージャーを使用すると、クロージャーから見える
そのスコープにある変数すべてがメモリ内に残ってしまう。
これはIEの循環参照のバグとは別の話。
そうだね。
(DOMとJavaScriptの)循環参照はメモリリークを招くという
古いIEのバグに関連する話で、
それを除けば循環参照してもよい。
ただ循環参照とハンドラの生存期間が長い問題は別の話で
ハンドラにクロージャーを使用すると、クロージャーから見える
そのスコープにある変数すべてがメモリ内に残ってしまう。
これはIEの循環参照のバグとは別の話。
>>649
script要素が通信(コードを実行する)のは、
新しくscript要素を作成してdocumentに挿入したときと、srcも中身もないscript要素にsrcをセットしたとき。
http://html.spec.whatwg.org/multipage/scripting.html#the-script-element:prepare-a-script
<script src="hoge.js"></script> ← srcを変えても二度と通信しない
<script>alert(123);</script> ← 中身が書かれているので、srcを変えても通信しない
<script></script> ← srcも中身もないので、srcや中身を変えると一度だけ実行する
まあ簡単に言うと、一つのscript要素につきスクリプトは一回しか実行されないってことです。
script要素が通信(コードを実行する)のは、
新しくscript要素を作成してdocumentに挿入したときと、srcも中身もないscript要素にsrcをセットしたとき。
http://html.spec.whatwg.org/multipage/scripting.html#the-script-element:prepare-a-script
<script src="hoge.js"></script> ← srcを変えても二度と通信しない
<script>alert(123);</script> ← 中身が書かれているので、srcを変えても通信しない
<script></script> ← srcも中身もないので、srcや中身を変えると一度だけ実行する
まあ簡単に言うと、一つのscript要素につきスクリプトは一回しか実行されないってことです。
>>664
循環参照にこだわるから、循環参照することは悪いのかって話になって
本当の問題が見えてこなくなる。
例えば、forEachでクロージャーを使っても循環参照する。だけどこれは問題ならない。
なぜならforEachのクロージャーの生存期間は凄く短いから。
本当の問題は、ハンドラであれば一般的にクロージャーの生存期間が長いことにある。
両方とも循環参照しているのに、一方は問題なくても一方は問題がある。
その理由は循環参照ではなくて、生存期間であるということに気づかないといけない。
それさえわかっていれば、クロージャーを使ってもいいことが理解できるはず。
本当の問題を理解せずに、わかりやすいからといってクロージャーは使ったらだめという
決まりを作ると、ルールだけが生き残ることになる。
循環参照にこだわるから、循環参照することは悪いのかって話になって
本当の問題が見えてこなくなる。
例えば、forEachでクロージャーを使っても循環参照する。だけどこれは問題ならない。
なぜならforEachのクロージャーの生存期間は凄く短いから。
本当の問題は、ハンドラであれば一般的にクロージャーの生存期間が長いことにある。
両方とも循環参照しているのに、一方は問題なくても一方は問題がある。
その理由は循環参照ではなくて、生存期間であるということに気づかないといけない。
それさえわかっていれば、クロージャーを使ってもいいことが理解できるはず。
本当の問題を理解せずに、わかりやすいからといってクロージャーは使ったらだめという
決まりを作ると、ルールだけが生き残ることになる。
>>666
> これremoveEventせずにDOMオブジェクトが消滅したらどうなるの?
DOMを消す時に、jQuery内部のcleanDataが呼ばれる。
cleanDataではDOMに関連づいたデータを全て消去する。
> これremoveEventせずにDOMオブジェクトが消滅したらどうなるの?
DOMを消す時に、jQuery内部のcleanDataが呼ばれる。
cleanDataではDOMに関連づいたデータを全て消去する。
>>647
> 繰り返すが、>>555で「↓なぜこれが循環参照になるのかというと」と明言している意図は?
古いIEでメモリリークする原因が、DOMとJavaScriptの間で
循環参照しているからだろ。「"DOMとJavaScriptの間で"循環参照してる」という
説明なしに、古いIEでメモリリークする理由を説明することは出来ない。
ここまでで一区切り。以下次の話として、
今の時代は古いIEは消えてしまったと考えていいものとする。
古いIEは消えてしまったのだから、循環参照しても問題ないよね?
そうは問屋が卸さない。
メモリリークの問題はなくなったが、
生存期間による不要なメモリ使用の問題は残っている。
これが今も起きてる注意すべき問題の話。
> 繰り返すが、>>555で「↓なぜこれが循環参照になるのかというと」と明言している意図は?
古いIEでメモリリークする原因が、DOMとJavaScriptの間で
循環参照しているからだろ。「"DOMとJavaScriptの間で"循環参照してる」という
説明なしに、古いIEでメモリリークする理由を説明することは出来ない。
ここまでで一区切り。以下次の話として、
今の時代は古いIEは消えてしまったと考えていいものとする。
古いIEは消えてしまったのだから、循環参照しても問題ないよね?
そうは問屋が卸さない。
メモリリークの問題はなくなったが、
生存期間による不要なメモリ使用の問題は残っている。
これが今も起きてる注意すべき問題の話。
そーゆーのってどうやってチェックするの?
タスクマネージャーを随時みるの?
タスクマネージャーを随時みるの?
ダミーのデータを使ってわざと数十MB単位でメモリを使うように
すればタスクマネージャーでもわかると思う
すればタスクマネージャーでもわかると思う
>>672
使われていないし、俺なら使わない
Mutation Event から Mutation Observers へ
http://standards.mitsue.co.jp/archives/001538.html
> “Detect DOM changes with Mutation Observers” で紹介されているように、
> DOM4 では Mutation Observers という新しいインタフェイス群が定義されました。
> これらを用いると、DOM2 Events で定義された Mutation Event を置きかえることができます。
>
> Mutation Event は数々の問題点を抱えていることが明らかになっています
> (策定中の DOM3 Events では該当箇所に警告文が記述されているほどです)。
> 例えばパフォーマンスに関わる問題があります。
jQueryでハンドラやデータを追加したのなら、jQueryで消さないとだめ。
ブラウザが勝手にDOMオブジェクトを消滅させることはないだろう。
(ページ移動は別。ページ移動時=unload時に解放していたはず)
jQueryで操作したならjQueryが使えるわけで、
それをjQuery以外で削除しようと思うことはあまりないと思うけどね。
使われていないし、俺なら使わない
Mutation Event から Mutation Observers へ
http://standards.mitsue.co.jp/archives/001538.html
> “Detect DOM changes with Mutation Observers” で紹介されているように、
> DOM4 では Mutation Observers という新しいインタフェイス群が定義されました。
> これらを用いると、DOM2 Events で定義された Mutation Event を置きかえることができます。
>
> Mutation Event は数々の問題点を抱えていることが明らかになっています
> (策定中の DOM3 Events では該当箇所に警告文が記述されているほどです)。
> 例えばパフォーマンスに関わる問題があります。
jQueryでハンドラやデータを追加したのなら、jQueryで消さないとだめ。
ブラウザが勝手にDOMオブジェクトを消滅させることはないだろう。
(ページ移動は別。ページ移動時=unload時に解放していたはず)
jQueryで操作したならjQueryが使えるわけで、
それをjQuery以外で削除しようと思うことはあまりないと思うけどね。
>>669
> 古いIEでメモリリークする原因が、DOMとJavaScriptの間で
> 循環参照しているからだろ。「
>>641で「巨大な配列がDOMでなければ循環参照しない」と指摘したはずだが、具体的に循環参照する「DOMオブジェクト」と「JavaScriptオブジェクト」は何だ?
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', function() {
alert(a.length);
alert(foo.name);
});
}
# 以下、戯言。
# 同じ内容を4回説明してようやく本題「循環参照しない」に入れたわけだが、何を答えてよいかわからない程の難問だったのかね…。
> 古いIEでメモリリークする原因が、DOMとJavaScriptの間で
> 循環参照しているからだろ。「
>>641で「巨大な配列がDOMでなければ循環参照しない」と指摘したはずだが、具体的に循環参照する「DOMオブジェクト」と「JavaScriptオブジェクト」は何だ?
function foo() {
var a = [巨大な配列];
window.addEventHandler('load', function() {
alert(a.length);
alert(foo.name);
});
}
# 以下、戯言。
# 同じ内容を4回説明してようやく本題「循環参照しない」に入れたわけだが、何を答えてよいかわからない程の難問だったのかね…。
>>675
それでお前が言いたいことは何なんだよ?w
それでお前が言いたいことは何なんだよ?w
>>680
お、気づいたかw
そこは間違ったなって思っていたところなんだよ。
で、お前は気づいているよな?
windowsはグローバル変数だから当てはまるけど、
var elm = document.getElementById('id'); なら
ローカル変数になるから当てはまらないということを
今更ながら訂正すると
function foo() {
var a = [巨大な配列];
var elm = document.getElementById('id');
elm.addEventListener('click', function() {
alert(a.length);
alert(foo.name);
}, false);
}
これは循環参照する。
お、気づいたかw
そこは間違ったなって思っていたところなんだよ。
で、お前は気づいているよな?
windowsはグローバル変数だから当てはまるけど、
var elm = document.getElementById('id'); なら
ローカル変数になるから当てはまらないということを
今更ながら訂正すると
function foo() {
var a = [巨大な配列];
var elm = document.getElementById('id');
elm.addEventListener('click', function() {
alert(a.length);
alert(foo.name);
}, false);
}
これは循環参照する。
>>682
「対象IEのバージョン」と「MSDNのソースURL」を教えてください
グローバルオブジェクト(DOM)を含む循環参照でもメモリリークするなら回避手段はないと思いますが、当時はどうしていたのでしょう?
「対象IEのバージョン」と「MSDNのソースURL」を教えてください
グローバルオブジェクト(DOM)を含む循環参照でもメモリリークするなら回避手段はないと思いますが、当時はどうしていたのでしょう?
>>660
今のブラウザなら大丈夫なはず
自分で確かめてないからアレだけど、検証結果がこのスレ(の過去スレ)にも貼られていた
ただしハンドラ内でeval()を使ったりすると、そこを通るまでaが参照されるか不明なので
aは残ってしまうだろうね
今のブラウザなら大丈夫なはず
自分で確かめてないからアレだけど、検証結果がこのスレ(の過去スレ)にも貼られていた
ただしハンドラ内でeval()を使ったりすると、そこを通るまでaが参照されるか不明なので
aは残ってしまうだろうね
>>686
その考え方が認められるのなら「a(Script)→foo(Script)」も成立するのでは?
function hoge () {
var p = document.createElement('p');
function foo () {
var div = document.createElement('div');
}
foo();
}
変数から上位スコープオブジェクトを参照可能とする場合、「div(DOM)→foo(Script)→p(DOM)」で循環参照が成立するが、勿論そんなことはない
ECMAScript 5 は関数スコープなので参照は関数単位で形成される
変数はスコープチェーンの過程で上位スコープを参照するだけ
その考え方が認められるのなら「a(Script)→foo(Script)」も成立するのでは?
function hoge () {
var p = document.createElement('p');
function foo () {
var div = document.createElement('div');
}
foo();
}
変数から上位スコープオブジェクトを参照可能とする場合、「div(DOM)→foo(Script)→p(DOM)」で循環参照が成立するが、勿論そんなことはない
ECMAScript 5 は関数スコープなので参照は関数単位で形成される
変数はスコープチェーンの過程で上位スコープを参照するだけ
ローカル変数はスコープチェーン上で始めに一番近い関数スコープから参照するのでグローバルスコープの参照は発生しえないね
a[1] == 1
このときaが配列じゃなかったら
Uncaught TypeError: Cannot read property '1' of null
ってエラーになりますが
a != null && a[1] == 1
って書くのが正解ですか?
このときaが配列じゃなかったら
Uncaught TypeError: Cannot read property '1' of null
ってエラーになりますが
a != null && a[1] == 1
って書くのが正解ですか?
たとえばさjsonpで取得した時ですよ
サーバから正常にデータを取得出来た時にaは配列になるけど
ただしいデータが送られて来なかった場合はaはnullになります
サーバから正常にデータを取得出来た時にaは配列になるけど
ただしいデータが送られて来なかった場合はaはnullになります
>>693
正しいデータが送られてこなかった場合は、
エラーなんだから、エラーでいいじゃん?
なんで正しいデータが送られてこない時にまで
そのエラーを握りつぶして、無理やり動かすようなことをするのさ?
正しいデータが送られてこなかった場合は、
エラーなんだから、エラーでいいじゃん?
なんで正しいデータが送られてこない時にまで
そのエラーを握りつぶして、無理やり動かすようなことをするのさ?
正しいデータが送られてこなかったら
エラーが発生しましたって表示させるか、
ログなどに表示して、そこに来る前に処理を打ち切るんだよ
エラーが発生しましたって表示させるか、
ログなどに表示して、そこに来る前に処理を打ち切るんだよ
本気でコード書いたらエラーチェックとエラー処理の方がコード量が多い事も普通
>>696
それは作り方が悪いな。
エラーを戻り値で返すパターンをやるとそうなる。
try-catchで捕まえてエラーをreturn -1とかするようなコードね。
例外を正しく使えばエラー処理のコードは少なくなるし、
JavaScriptの場合、window.onerrorで未知のエラーを
一括して捕まえることも出来る。
それは作り方が悪いな。
エラーを戻り値で返すパターンをやるとそうなる。
try-catchで捕まえてエラーをreturn -1とかするようなコードね。
例外を正しく使えばエラー処理のコードは少なくなるし、
JavaScriptの場合、window.onerrorで未知のエラーを
一括して捕まえることも出来る。
>>698
正しくねーよw
そういうのは、エラーコードをラップした
エラーオブジェクトを作ってthrowするもんだ。
そうすれば、エラーメッセージ等は
そのエラーオブジェクトに処理を任せられる。
そして特殊な処理をしたい場合だけcatchすればいい。
> try-catchで括るのは単に楽してるだけ
当たり前だろ。戻り値でエラーを返すやり方では面倒だから
ほぼ全ての言語に例外が搭載されたんだぞ。
楽して対応できるのだから、そっちのほうがいいだろ。
正しくねーよw
そういうのは、エラーコードをラップした
エラーオブジェクトを作ってthrowするもんだ。
そうすれば、エラーメッセージ等は
そのエラーオブジェクトに処理を任せられる。
そして特殊な処理をしたい場合だけcatchすればいい。
> try-catchで括るのは単に楽してるだけ
当たり前だろ。戻り値でエラーを返すやり方では面倒だから
ほぼ全ての言語に例外が搭載されたんだぞ。
楽して対応できるのだから、そっちのほうがいいだろ。
>>699
> そういうのは、エラーコードをラップした
> エラーオブジェクトを作ってthrowするもんだ。
それだったら結局同じことをやっているに過ぎない
try-catchを使えば楽になるなんて迷信だ
> そういうのは、エラーコードをラップした
> エラーオブジェクトを作ってthrowするもんだ。
それだったら結局同じことをやっているに過ぎない
try-catchを使えば楽になるなんて迷信だ
前へ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 次へ / 要望・削除依頼は掲示板へ / 管理情報はtwitterで / JavaScript スレッド一覧へ
みんなの評価 : 類似してるかもしれないスレッド
- + JavaScript の質問用スレッド vol.122 + (116) - [100%] - 2018/5/2 18:30
- + JavaScript の質問用スレッド vol.125 + (1001) - [97%] - 2015/10/7 17:45
- + JavaScript の質問用スレッド vol.123 + (966) - [97%] - 2020/10/20 2:30
- + JavaScript の質問用スレッド vol.120 + (1002) - [97%] - 2014/11/8 1:15
- + JavaScript の質問用スレッド vol.124 + (1001) - [97%] - 2015/7/16 1:30
- + JavaScript の質問用スレッド vol.121 + (1001) - [97%] - 2022/11/29 16:30
- + JavaScript の質問用スレッド vol.132 + (1001) - [97%] - 2018/4/19 11:00
- + JavaScript の質問用スレッド vol.142 + (984) - [97%] - 2020/8/27 19:15
- + JavaScript の質問用スレッド vol.112 + (1001) - [97%] - 2013/11/27 16:46
- + JavaScript の質問用スレッド vol.121 + (1001) - [97%] - 2015/1/1 18:30
- + JavaScript の質問用スレッド vol.129 + (981) - [97%] - 2016/5/5 8:16
- + JavaScript の質問用スレッド vol.129 + (926) - [97%] - 2017/7/27 13:45
- + JavaScript の質問用スレッド vol.128 + (1001) - [97%] - 2016/2/26 6:45
- + JavaScript の質問用スレッド vol.123 + (1002) - [97%] - 2015/4/27 23:30
- + JavaScript の質問用スレッド vol.127 + (1001) - [97%] - 2016/2/4 0:15
- + JavaScript の質問用スレッド vol.127 + (160) - [97%] - 2021/7/16 9:30
- + JavaScript の質問用スレッド vol.142 + (926) - [97%] - 2019/12/23 13:15
トップメニューへ / →のくす牧場書庫について