这就是我的意思。我正在练习面向对象的Javascript(我通过练习学习),为了好玩而创建了以下课程
function Funcstack ( )
{
this.stack = []; // stack/array of functions w/ no params
this.pushFunction = function ( f )
{
// f: function w/ no params
this.stack.push(f);
}
this.popFunction = function ( f )
{
// f: function w/ no params
var n = this.stack.length;
if (n > 0) this.stack.splice(n - 1, 1);
}
this.executeFunctions = function ( )
{
// execute functions from top to bottom of stack
for ( var i = (this.stack.length - 1); i >= 0; --i )
{
var thisfunc = this.stack[i];
thisfunc();
}
}
}
var fs = new Funcstack();
fs.pushFunction(function() { console.log('z'); });
fs.pushFunction(function() { console.log('y'); });
fs.pushFunction(function() { console.log('x'); });
fs.executeFunctions(); // should print 'xyz'
并且对它起作用感到惊讶。主要原因是因为我认为,例如,
this.pushFunction = function ( f )
{
// f: function w/ no params
this.stack.push(f);
}
函数的主体不会识别this.stack
,因为特定上下文中的this
指的是调用函数pushFunction
,它没有名为{的成员{1}}!所以我认为它抬高了范围链是正确的吗?这似乎与stack
的整个想法相矛盾,但是......它的重点是什么?
答案 0 :(得分:3)
简短的回答是“不”。执行上下文的 this 总是在当前执行上下文中解析,因此它与作用域无关。使用宽箭头函数,它设置为与外部执行上下文相同的值。
函数的 this 由函数的调用方式或 bind 设置决定。它不是词法设置(调用在代码中)或调用函数的地方。
这个是一个对象(总是处于非严格模式),然后解析其属性的方式与解析任何对象属性的方式相同,首先是自身,然后是[[Prototype]]
链。将函数作为对象的方法调用的地方:
fs.executeFunctions();
然后基础对象(fs)在函数中设置为 this 。因此,当 this.stack.length 被解析时, this 引用 fs 实例, executeFunctions 被解析为 fs 的属性。
答案 1 :(得分:0)
它起作用的原因是因为调用上下文。
this.stack = []; //< ---是Funstack
的任何实例的实例属性(成员)
使用“fs”(实例引用)调用“pushFunction”来引用
“this”(上下文)成为“fs”对象的任何内容..
如果仍不清楚,请尝试在javascript的“调用上下文”中阅读更多内容。
答案 2 :(得分:0)
当您说:var fs = new Funcstack();
时,您正在声明一个对象,该对象是类Funcstack
的一个实例。请注意,在constructor
内,您要声明它的一些属性和方法。
因此,所有这些方法中的关键字this
都会引用您创建的对象。如果需要,您可以随时使用call
,apply
或bind
更改上下文。
请注意,您通过说:pushFunction
将this.pushFunction = function(f) { /* (...) */ }
声明为该班级的成员。所以,你要在课堂上创建一个方法。这就是为什么this
关键字引用作为该类实例的对象的原因。
如果您将函数声明为var pushf = function(f) { /* (...) */ }
,然后在类Funcstack
的某个方法中调用该函数,则会出现错误:
TypeError:this.stack未定义
看一下下面的例子。
function Funcstack() {
this.stack = []; // stack/array of functions w/ no params
var pushf = function _pushFunction(f) {
this.stack.push(f);
}
this.pushFunction = function(f) {
// f: function w/ no params
pushf(f);
}
this.popFunction = function(f) {
// f: function w/ no params
var n = this.stack.length;
if (n > 0) this.stack.splice(n - 1, 1);
}
this.executeFunctions = function() {
// execute functions from top to bottom of stack
for (var i = (this.stack.length - 1); i >= 0; --i) {
var thisfunc = this.stack[i];
thisfunc();
}
}
}
var fs = new Funcstack();
fs.pushFunction(function() {
console.log('z');
});
fs.pushFunction(function() {
console.log('y');
});
fs.pushFunction(function() {
console.log('x');
});
fs.executeFunctions(); // should print 'xyz'