(我已经修改了四次问题,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`?
答案 0 :(得分:1)
回答你的第一个问题:
CASE
实际上根本没有参考功能。它与函数的执行上下文有关(即从函数中调用函数)。
您的函数this
是全局定义的,因此当您在代码中的各种函数内部调用custLog
时,您实际上正在执行对该全局函数的引用,并在技术上调用该函数中定义的函数。全球范围。因此,'custLog'的执行上下文(在代码中调用它)是全局对象。所有全局定义的函数和变量都存在于全局对象(在浏览器中,恰好是窗口对象)中,这是custLog
引用的内容。
有些方法可以使用this
,this
和call
等方法更改apply
引用的内容,但我建议您至少阅读关于JavaScript的bind
关键字(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this)
答案 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