我写了一个JavaScript函数,它运行得很好,但它很长,所以我想把它分解成更小的函数。我认为这很容易(也许是这样)但是我遇到了问题!
所以我的代码结构如下:
getPosition: function(a) {
if (true) {
position = this.getPoint(a);
}
},
getPoint: function(a) {
var position;
var options = a.target.parentElement.children;
[].forEach.call(options, function(option){
if (option.type == "point") {
position = this.getNewPoint(a, option);
} else if (option.type == "line") {
position = this.getNewLine(a, option);
}
}
return position;
},
getNewPoint: function(a, option){
...
return point;
},
getNewLine: function(a, option){
...
return line;
}
尝试此操作时,我发现错误this.getNewPoint
和this.getNewLine
未定义。这有意义,因为范围,所以我决定尝试使用回调:
getPosition: function(a) {
if (true) {
position = this.getPoint(a, this.getNewPoint, this.getNewLine);
}
},
getPoint: function(a, pointCallback, lineCallback) {
var position;
var options = a.target.parentElement.children;
[].forEach.call(options, function(option){
if (option.type == "point") {
position = pointCallback(a, option);
} else if (option.type == "line") {
position = lineCallback(a, option);
}
}
return position;
},
getNewPoint: function(a, option){
...
return point;
},
getNewLine: function(a, option){
...
return line;
}
这个get是要调用的函数,但是,(我猜是这样的)因为Javascript的异步性质,代码在没有回调完成的情况下继续,所以永远不会返回返回值。看起来当我输入一些console.log()
进行测试时,它开始工作了。我猜这是因为它迫使代码放慢速度。有什么想法吗?
更新:
由于我收到的非常棒的帮助,我已经让它工作到了一定程度。因此,只要永远不会调用getNewLine
函数,它就可以正常工作。所以我认为我的getNewLine
函数返回的方式有问题,因为它打破了一切!所以这是关于该功能的更多细节:
getNewLine: function(a, option){
var line;
var endPoints = option.points;
for (var i = 0; i < (endPoints.length - 1); i++) {
... math here
if (distance <= linePadding) {
if (true) {
line = option;
return line; //Want to break the loop and for the function to return
}
}
}
return line;
}
答案 0 :(得分:2)
你没有介绍任何真正异步的东西,只是一种应用函数的不同方法。与使用回调相比,您的问题更容易解决;保存对正确的this
:
getPoint: function(a) {
var self = this; // <--
var options = a.target.parentElement.children;
[].forEach.call(options, function(option){
if (option.type == "point") {
newPoint = self.getNewPoint(a, option); // <--
} else if (option.type == "line") {
newLine = self.getNewLine(a, option); // <--
}
});
},
至于为什么你的新解决方案不起作用,看起来你没有用正确的上下文传递回调。首先,我相信你打算输入
position = this.getPoint(a, this.getNewPoint, this.getNewLine);
但问题是你再次失去正确的this
上下文。您可以通过使用.bind
position = this.getPoint(a, this.getNewPoint.bind(this), this.getNewLine.bind(this));
Bind创建给定函数的副本,其中this
上下文已明确设置。
我实际上写了一个答案,解释this
如何确定here。正如费利克斯·克林所指出的那样,.forEach
接受另一个论证来设定this
的背景:
[].forEach.call(options, function(option) {
// Your same code as before
}, this); // <-- Set the context
答案 1 :(得分:1)
这里有 no 异步代码。仅仅因为你将函数作为参数传递并不意味着它是异步的。
您遇到的问题是 getPoint
没有返回任何内容!您需要return
语句才能返回任何内容。
对于第一个示例,每次输入新this
时,function(){}
的值都会更改。 this
基于函数的调用方式。在forEach
内,this
是&#34;数组中的元素&#34; 全局window
对象,而不是您的对象。
你可以&#34;备份&#34; 您可以通过在回调后传递this
变量,然后在forEach
内使用。this
来设置forEach
的值。< / p>
getPoint: function(a) {
var options = a.target.parentElement.children,
position;
[].forEach.call(options, function(option){
if (option.type == "point") {
position = this.getNewPoint(a, option);
} else if (option.type == "line") {
position = this.getNewLine(a, option);
}
}, this);
return position;
},
答案 2 :(得分:-3)
您认为this
正在改变范围。 this
始终指向最近的父函数。因此,如果将代码分成多个函数,this
变量将根据函数而变化。
解决此问题的一种方法是,当从另一个函数调用一个函数时,您可以使用this
或.call
方法在函数中设置.apply
。
.call
将this
范围作为第一个参数,以下所有参数都是传递给被调用函数的实际参数。 (argument = parameter -1)。
.apply
将this
范围作为第一个参数,其第二个参数是一个数组,它将作为参数传递给被调用函数。
所以在这种情况下我会建议
getPosition: function(a) {
if (true) {
position = this.getPoint.call(this, a);
}
},
getPoint: function(a) {
var position;
var options = a.target.parentElement.children;
[].forEach.call(options, function(option){
if (option.type == "point") {
position = this.getNewPoint.call(this, a, option);
} else if (option.type == "line") {
position = this.getNewLine.call(this, a, option);
}
}
return position;
},
getNewPoint: function(a, option){
...
return point;
},
getNewLine: function(a, option){
...
return line;
}