2016-07-26 4 views
0

(質問を4回修正しました.custLogの変更部分は対応する変更番号でコメントアウトされています。前のバージョン - この説明の最後にあります)Loggin関数のスコープとこれ。 TypeError:custLog(...)。bindは関数ではありません

窓、内外の関数にthisの値を表示しようとしました。

<script type="text/javascript"> 

    //HELPING function 
     function whatTypeFnc(obj) { 
      // Angus Croll https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ 
      return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); //array, object, function 
     };  

    //The last changes, the custLog up to date. 
//CustLog is helping function to log if the variables in array names are in the scope of the calling function, and to log their values. 
    var custLog = function (num) { 
      var nameF = this; 
      var names = ['outerVal', 'later', 'innerVal' , 'innerF', 'paramVal', 'tooLate', 'outerF']; 
      var ans = num + ' ' + nameF + " : "; //nameF = : , 
      if (this) { names.forEach(function(item, index, array) { 
        try { 
         var nameVar = eval(item); 
         if(eval(nameVar)) { 
          if (whatTypeFnc(nameVar) !== 'function') { 
           ans+= item + ' = ' + nameVar + ', '; 
          } else { ans+= item + ' = function, '; } } } 
        catch (e) { ans+= item + ' = und, '; } 
      }); } 
      console.log(ans); 
      return ans; 
    }; 

    // the code where i use custLog() to log information about the application specific scope of inner, outer functions and window. 

    var outerVal = 'outerVal'; 
    var later; 
    var that = this; //refers to window 

    function outerF() { 
     var that = this; 
     //custLog('43').bind(this); //gives the same error: TypeError: custLog(...).bind is not a function. 
     custLog('43').bind(that); 
     var innerVal = 'innerVal'; 

     function innerF(paramVal) {  
      var that = this; 
      console.log('innerF this='+this); 
      custLog('47').bind(that); 
      assert(outerVal, "Inner can see the outerVal."); 
      assert(innerVal, "Inner can see the innerVal."); 
      assert(paramVal, "Inner can see the later_second."); 
      assert(tooLate, "Inner can see the tooLate,");    
     } 
     custLog('53').bind(that); 
     later = innerF; 
    }; 

custLog('56').bind(that); //gives the error that custLog('56').bind is not a function 
assert(!tooLate,"Outer can't see the tooLate");     
var tooLate = 'tooLate'; 
custLog('59').bind(that); 
outerF(); 
custLog('61').bind(that); 
later('later_second'); 
custLog('63').bind(that); 

I am getting the TypeError: `custLog(...).bind is not a function`. Custlog is the following: 
56 [object Window] : outerVal = outerVal, innerVal = und, innerF = und, paramVal = und, outerF = function, 
TypeError: custLog(...).bind is not a function 
error source line: custLog('56').bind(that); 

// ***************************************** ****** 質問の前のコード。問題は、thisが関数変数を参照していないことでした。それは以下のコメントによって答えられましたが、今他のエラーが発生しました。実際には全く機能に戻って参照していない

this:あなたの最初の質問に答えるために

I try to print value of `this` in window, inner and outer functions. My logs does not coincide with assert log. Why? 
On line 47 `this` refers to `window` instead of `innerF`, one lines 43 and 53 - to `window` instead of `outerF`. Why? 
Why i do not got logged `innerF` on line 47? 


     // Helping function for assertion and type checking are the same . 
    function assert(value, desc) { .. }; 
    functio whatTypeFnc(obj) { ... }; 

    var outerVal = 'outerVal'; 
    var later; 
    var that = this; //refers to window 

    function outerF() { 
     var that = this; 
     console.log('innerF this='+this); 
     //custLog('43').bind(this); //gives the same error: TypeError: custLog(...).bind is not a function. 
     custLog('43').bind(that); 
     var innerVal = 'innerVal'; 

     function innerF(paramVal) {  
      var that = this; 
      console.log('innerF this='+this); 
      custLog('47').bind(that); 
      assert(outerVal, "Inner can see the outerVal."); 
      assert(innerVal, "Inner can see the innerVal."); 
      assert(paramVal, "Inner can see the later_second."); 
      assert(tooLate, "Inner can see the tooLate,");    
     } 
     custLog('53').bind(that); 
     later = innerF; 
    }; 

    custLog(that, '56'); 
    assert(!tooLate,"Outer can't see the tooLate");     
    var tooLate = 'tooLate'; 
    custLog(that, '59'); 
    outerF(); 
    custLog(that, '61'); 
    later('later_second'); 
    custLog(that, '63'); 

//The previous question custLog 
var custLog = function (ArrObj, num) { 
      var nameF = this; 
      if (ArrObj) { nameF = ArrObj.toString(); } //does not work 
      else { nameF=ArrObj; } 
      var names = ['outerVal', 'later', 'innerVal' , 'innerF', 'paramVal', 'tooLate', 'outerF']; 
      var ans = num + ' ' + nameF + " : "; //nameF = : , 
     if (ArrObj) { names.forEach(function(item, index, array) { 
       try { var nameVar = eval(item); 
        if(eval(nameVar)) { 
         if (whatTypeFnc(nameVar) !== 'function') { 
          ans+= item + ' = ' + nameVar + ', '; 
         } else { ans+= item + ' = function, '; } } } 
       catch (e) { ans+= item + ' = und, '; } 
      }); } 
       /* var descr = Object.getOwnPropertyDescriptor(ArrObj, item); 
       if(descr) { 
        if(ArrObj.hasOwnProperty(item)) { 
         if (whatTypeFnc(ArrObj[item]) !== 'function') { 
          ans+= item + ' = ' + descr.value + ', '; 
         } else { ans+= item + ' = function, '; } } } */ 
      console.log(ans); 
      return ans; 
    }; 

// Helping function for assertion. 
    //From Secrets of JavaScript Ninja by John Resig, Bear Bibeault 
function assert(value, desc) { 
    var resultsList = document.getElementById("results"); 
    if (!resultsList) { 
    resultsList = document.createElement('ul'); 
    document.getElementsByTagName('body')[0].appendChild(resultsList); 
    resultsList.setAttribute('id','results'); 
    } 
    var li = document.createElement("li"); 
    li.className = value ? "pass" : "fail"; 
    li.appendChild(document.createTextNode(desc)); 
    resultsList.appendChild(li); 
} 


The assert results are : 

    Outer can't see the tooLate 
    Inner can see the outerVal. 
    Inner can see the innerVal. 
    Inner can see the later_second. 
    Inner can see the tooLate, 

The log results are : 

    56 [object Window] : outerVal = outerVal, later = undefined, tooLate = undefined, outerF = function, 
    59 [object Window] : outerVal = outerVal, later = undefined, tooLate = tooLate, outerF = function, 
    43 [object Window] : outerVal = outerVal, later = undefined, tooLate = tooLate, outerF = function, 
    53 [object Window] : outerVal = outerVal, later = undefined, tooLate = tooLate, outerF = function, 
    61 [object Window] : outerVal = outerVal, later = function, tooLate = tooLate, outerF = function, 
    47 [object Window] : outerVal = outerVal, later = function, tooLate = tooLate, outerF = function, 
    63 [object Window] : outerVal = outerVal, later = function, tooLate = tooLate, outerF = function, 

Why `this` refer to `[object Window]` instead of `innerF` on line 47, or `outerF` on lines 43 and 53? 

Why on line 47, my log does not see `innverVal=innerVAL` and `paramVal=later_Second`? 
+0

あなたが関数を呼び出すときthis' 'の値を設定する必要がある場合は、[Function.prototype.call](https://developer.mozilla.org/en-US/docs/Web/JavaScriptを参照してください/ Reference/Global_Objects/Function/call)と[Function.prototype.apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) – csum

+0

ですそこから電話しています。 –

答えて

1

。これは、関数の実行コンテキスト(関数が呼び出された場所)に関係します。

関数custLogがグローバルに定義されているため、コード内のさまざまな関数の中でcustLogを呼び出すと、実際にそのグローバル関数への参照が実行され、グローバルスコープで定義された関数が技術的に呼び出されます。したがって、 'custLog'の実行コンテキストは、コード内で呼び出すときにグローバルオブジェクトです。すべてのグローバルに定義された関数と変数は、グローバルオブジェクト(ブラウザではウィンドウオブジェクトになる)内に存在し、それはthisが参照するものです。

は、あなたがメソッドのようなcallapplybindを使用してthisが参照するものを変更することができる方法がありますが、私には、JavaScriptのthisキーワード(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this

+0

私は 'custLog'関数で' this'を使用しません。私は 'innerF'文' custLog(this、 'msg') 'でそれを使用します。したがって、 'custLog'の' ArrObj'は 'innerF'の' this'値を持っていますか?私は間違っている? – olga

+0

私は 'TypeError:custLog(...)を与えた' custLog( 'num')。bind(this); 'しようとしました。 – olga

+0

JavaScriptで 'this'がどのように動作するかを理解するために、この記事http://www.quirksmode.org/js/this.htmlを読むことをお勧めします。 「これ」の範囲を時々把握するのは難しいかもしれません。 '.bind()'関数に関しては、どこで使用しているのかわかりませんが、この記事はそれをよく読んでいます。https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_objects /関数/バインド –

0

I上のMDNの文書を少なくとも読みを示唆していますnice custLog(msg).bind(this)関数を作成できませんでした。 例と提案これを行う方法は大歓迎です。

この回答は、特定の機能の範囲を確認する方法をデモストレートしたもので、これが私の目的でした。私の素敵なcustLog(MSG).bind(この)関数を作るために管理することができませんでした、木は5行を使用し、私はスコープをログインするたび集約:

tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
namesG.forEach(function(item, index, array) { 
    try { eval(item); myCallback(item, index, array, eval(item)); 
    } catch (e) { myCallback(item, index, array, 'er'); }    
}); console.log(logs); tind+=1; 

それにもかかわらず、私は関数スコープのログ記録について、オンライン任意の例を見つけることができませんでした。 したがって、このコードは、一部の初心者が範囲を理解しようとすると役に立ちます。

// The idea is that if we have a code as this : 
var Ass_inF; //will be Assigned to inF 
function outF() { 
....var inV1 = Math.random(); 
....function inF(paramVal) { } 
........Ass_inF = inF; 
}//outF 
outF(); 
Ass_inF('final1'); 
outF(); 
Ass_inF('final2'); 

我々はouther機能outFが実行を終了したという事実にもかかわらず、inner機能Ass_inF範囲でinV1値を保存することができます。 一方、私はこれのアプリケーションが表示されません。 なぜ値を別の関数スコープに格納するのですか? グローバル変数に直接格納することができます。グローバル変数に格納する場合、いつでも関数にアクセスできます。

<script type="text/javascript"> 

//出力例は、このようなものです

function whatTypeFnc(obj) { 
    // Angus Croll https://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ 
    return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); //array, object, function 
};  

//console logs that outV='+eval('outV')=outV, item=outV=outV, itemVal =outV 
//but innerHTML is empty 
function myCallback(item, index, array, itemVal) { 
    //console.log('inside myCallback 0, item='+ item+', itemVal=' + itemVal); 
    if (whatTypeFnc(itemVal) !== 'function') { 
     if(itemVal === 'undefined') { tableObj[tind][item] = '| und'; } 
     else if(itemVal==='') { tableObj[tind][item] = '| empty'; } 
     else if(itemVal===null) { tableObj[tind][item] = '| null'; } 
     else { tableObj[tind][item] = '| '+itemVal; } 
     logs+= item + ' = ' + itemVal + '; '; 
    } else { tableObj[tind][item] = '| fnc' ; logs+= item + ' = function; '; } 
    //console.log('inside myCallback outV='+eval('outV')+' , item='+item+'='+eval(item), ', itemVal ='+itemVal); 
    return logs; 
} 

var logs, msg, table, rowcnt, cellcnt, row, tableObj, tind; 
var namesG = ['outV', 'inV1', 'inV2', 'Ass_inF', 'outF', 'inF', 'paramVal', 'tooLate' ]; 

var outV = 'outV'; 
var Ass_inF, AssP_inF; 
logs = ''; //used for looing scope variables 

tableObj={}; tableObj[0]={}; tableObj[0]['msg'] = 'messages // variables'; 
for (let item of namesG) { tableObj[0][item]=item; } tind=1; 

    msg='67, initial, before outF, global scope '; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 

function outF() { 
    var inV1 = Math.random(); 

    /*msg='82, in outF '; tableObj[tind]={}; tableObj[tind]['msg']=msg;logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { if (eval(item)) { myCallback(item, index, array, eval(item)); } 
     } catch (e) { myCallback(item, index, array, 'und'); }    
    }); console.log(logs); tind+=1;*/ 

    function inF(paramVal) { 
     var inV2 = 'inV2'; 
     msg='89, in inF(paramVal) '; 
     tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
     namesG.forEach(function(item, index, array) { 
      try { eval(item); myCallback(item, index, array, eval(item)); 
      } catch (e) { myCallback(item, index, array, 'er'); }    
     }); console.log(logs); tind+=1; 

    };//inF 

    Ass_inF = inF; 
    msg='98, in outF, after Ass_inF = inF '; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 


    Ass_inF(); 
    msg='106, in outF, after Ass_inF() '; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 

    Ass_inF('Ass_1'); 
    msg='113, in outF, after Ass_inF(Ass_1); '; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 

}; 

var tooLate = 'tooLate'; 
outF(); 
    msg='124, after outF() '; tableObj[tind]={}; 
    tableObj[tind]['msg']=msg;logs=msg+" : ";  
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 

Ass_inF('final trial 1'); 
    msg='131, final, after Ass_inF(final trial 1) '; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 


    outF(); 
    msg='138, after outF() '; tableObj[tind]={}; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 

    Ass_inF('final trial 2'); 
    msg='145, final, after Ass_inF(final trial 2) '; 
    tableObj[tind]={}; tableObj[tind]['msg']=msg; logs=msg+" : "; 
    namesG.forEach(function(item, index, array) { 
     try { eval(item); myCallback(item, index, array, eval(item)); 
     } catch (e) { myCallback(item, index, array, 'er'); }    
    }); console.log(logs); tind+=1; 

//Display scope information 
table = document.createElement("TABLE"); 
// table.style="1px solid black"; does not work for cells and rows 
for (let indy in tableObj) { 
    row = table.insertRow(indy); cntx=0;  
    cell = row.insertCell(cntx); cell.innerHTML = indy+' ** '; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['msg']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['outV']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['inV1']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['tooLate']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['inV2'];cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['paramVal']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['Ass_inF']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['outF']; cntx++; 
    cell = row.insertCell(cntx); cell.innerHTML = tableObj[indy]['inF']; cntx++; 
    // ['outV', 'Ass_inF', 'AssP_inF', 'inV1', 'outF', 'inF', 'paramVal', 'tooLate' ]; 
    // for (let indx in tableObj[indy]){ cell = row.insertCell(indx); cell.innerHTML = tableObj[indy][indx]; } 
} 
document.body.appendChild(table); 

    </script> 

をロギングする範囲についての完全なスクリプト。

0 ** messages // variables outV inV1 tooLate inV2 paramVal Ass_inF outF inF 
1 ** 67, initial, before outF, global scope | outV | er | undefined | er | er | undefined | fnc | er 
2 ** 98, in outF, after Ass_inF = inF | outV | 0.6047199716839021 | tooLate | er | er | fnc | fnc | fnc 
3 ** 89, in inF(paramVal) | outV | 0.6047199716839021 | tooLate | inV2 | undefined | fnc | fnc | fnc 
4 ** 106, in outF, after Ass_inF() | outV | 0.6047199716839021 | tooLate | er | er | fnc | fnc | fnc 
5 ** 89, in inF(paramVal) | outV | 0.6047199716839021 | tooLate | inV2 | Ass_1 | fnc | fnc | fnc 
6 ** 113, in outF, after Ass_inF(Ass_1);  | outV | 0.6047199716839021 | tooLate | er | er | fnc | fnc | fnc 
7 ** 124, after outF() | outV | er | tooLate | er | er | fnc | fnc | er 
8 ** 89, in inF(paramVal) | outV | 0.6047199716839021 | tooLate | inV2 | final trial 1 | fnc | fnc | fnc 
9 ** 131, final, after Ass_inF(final trial 1) | outV | er | tooLate | er | er | fnc | fnc | er 
10 ** 98, in outF, after Ass_inF = inF | outV | 0.5665007054858299 | tooLate | er | er | fnc | fnc | fnc 
11 ** 89, in inF(paramVal) | outV | 0.5665007054858299 | tooLate | inV2 | undefined | fnc | fnc | fnc 
12 ** 106, in outF, after Ass_inF() | outV | 0.5665007054858299 | tooLate | er | er | fnc | fnc | fnc 
13 ** 89, in inF(paramVal) | outV | 0.5665007054858299 | tooLate | inV2 | Ass_1 | fnc | fnc | fnc 
14 ** 113, in outF, after Ass_inF(Ass_1);  | outV | 0.5665007054858299 | tooLate | er | er | fnc | fnc | fnc 
15 ** 138, after outF() | outV | er | tooLate | er | er | fnc | fnc | er 
16 ** 89, in inF(paramVal) | outV | 0.5665007054858299 | tooLate | inV2 | final trial 2 | fnc | fnc | fnc 
17 ** 145, final, after Ass_inF(final trial 2) | outV | er | tooLate | er | er | fnc | fnc | er 
関連する問題