Loggin函数范围,这个。 TypeError:custLog(...)。bind不是函数

时间:2016-07-26 23:20:47

标签: javascript logging scope this

(我已经修改了四次问题,custLog中更改的部分被注释掉了相应的更改编号。最新的custLog()位于顶部,以前的版本 - 位于本说明的底部。)

我尝试在窗口,内部和外部函数中打印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没有引用函数变量。下面的评论回答了这个问题,但现在出现了其他错误。

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`?

2 个答案:

答案 0 :(得分:1)

回答你的第一个问题:

CASE实际上根本没有参考功能。它与函数的执行上下文有关(即从函数中调用函数)。

您的函数this是全局定义的,因此当您在代码中的各种函数内部调用custLog时,您实际上正在执行对该全局函数的引用,并在技术上调用该函数中定义的函数。全球范围。因此,'custLog'的执行上下文(在代码中调用它)是全局对象。所有全局定义的函数和变量都存在于全局对象(在浏览器中,恰好是窗口对象)中,这是custLog引用的内容。

有些方法可以使用thisthiscall等方法更改apply引用的内容,但我建议您至少阅读关于JavaScript的bind关键字(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this

的MDN文档

答案 1 :(得分:0)

我无法设置好的custLog(msg).bind(this)功能。 欢迎提供如何做到这一点的示例和建议。

这个答案阐述了如何检查具体的功能范围,这是我的目标。我无法设法制作好的custLog(msg).bind(this)函数,每当我记录范围时,你都会使用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');

我们可以在inV1函数inner范围内保存Ass_inF值,尽管outher函数outF已完成执行。 另一方面,我没有看到这个的应用。 为什么要将值存储在另一个函数范围内? 我们可以成功地将它直接存储在某个全局变量中。如果我们存储在全局变量中,那么我们可以在任何函数中访问它。

    <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