今日、コードを書いていて、ふと、JavaScriptの仕組みがよくわからなくなりました。(JavaScriptに限った話ではないのかもしれません)
以下はそのコードを質問用に簡略化したコードなのですが、関数式の代入先オブジェクトを関数に渡すコールバック関数の中で参照出来るのは、どういう仕組みからなのでしょうか?(質問1)
function makeNewObj(obj, callback) { // いろいろな処理がこの辺に //非同期コールバック callback(); // 新しいオブジェクトを返します。 return {new: true}; } function asyncCallback() { setTimeout(function() { console.log(newObj); }, 0) } const obj = {}; const newObj = makeNewObj(obj, asyncCallback); // 実行するとnewObjを参照出来ているのは、どういう仕組みなのか? // { new: true }
とりあえず僕的にはこういうことが可能らしいということはわかったのですが、直感的ではないと感じていて、これは良い作法なのかどうかも気になります。(質問2)
もし、これが良い作法ではない場合、このようにコールバックの中で代入先を参照したいような場合に、どのような方法が取れるのかを教えて頂けると嬉しいです。(質問3)
const newObj = makeNewObj(obj, function asyncCallback() { setTimeout(function() { console.log(newObj); }, 0) });
ちなみにこう書くと直感的度は増すものの、これが良い作法なのかどうかは、やはり疑問が僕的に残ります。
※駄文となってしまっため、疑問部分に(質問1、2、3)のように添えましたが、全てにご回答頂かなくてももちろん構いませんm(_ _)m
質問に含めているコードの超簡略化バージョン
function run() { console.log(test); } const test = 3; run();
少し時間を置いていたら、単純にこのレベルまで簡略化できる話なのだと思いました。
miyabi-sunさんのご指摘をコードに反映
質問に掲載しているコードがコールバックになっていないというご指摘を受けましたので、反映致しました。(※ 今回の質問用のコードを用意する上で、ご指摘を受けた部分は質問の趣旨からして不要と判断したたため、質問時に省いておりました)
function makeNewObj(obj, callback) { // いろいろな処理がこの辺に //非同期コールバック callback(null, 'value'); // 新しいオブジェクトを返します。 return {new: true}; } function asyncCallback(err, value) { setTimeout(function() { if (err) throw err; // newObjを参照して行う諸々の処理(書き換えはしない) console.log(newObj); //最終的な実行処理 console.log(value); }, 0) } const obj = {}; const newObj = makeNewObj(obj, asyncCallback);
解決後の報告
1. 質問1に対する疑問
これは僕のJavaScirptのhoistingに対する理解が不足している為でした。kei344さんから頂いた回答やコメントをきっかけに、信頼できそうな情報源を元に、JavaScriptがどのようにコンパイルフェーズと実行フェーズでどのような処理を行っているのかを調べまして、よく理解が出来ました。
2. 質問2と質問3に対する疑問
質問に掲載したコード(miyabi-sunさんの指摘を反映したもの)をthink49さんから頂いた改善案をもとにテコ入れした結果、以下のようになりました。
function makeNewObj(obj, callback) { // いろいろな処理がこの辺にあると仮定。以下は超簡略版。 const newObj = Object.assign({}, obj, {new: true}); //非同期コールバック callback(null, newObj); // 新しいオブジェクトを返します。 return newObj; } function asyncCallback(err, newObj) { setTimeout(function() { if (err) throw err; // newObjを参照して行う諸々の処理(書き換えはしない) console.log(newObj); //最終的な実行処理 console.log('done'); }, 0) } const obj = {id: 1}; const newObj = makeNewObj(obj, asyncCallback);
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/11 08:33
2018/04/11 08:35
2018/04/11 08:37
2018/04/11 08:38
2018/04/11 08:42
2018/04/11 08:46
2018/04/11 08:48
2018/04/11 08:50
2018/04/11 08:52
2018/04/11 09:00
2018/04/11 09:40
2018/04/11 12:48