Javascript 回调函数缺少所需数据的作用域
我遇到了回调函数的变量丢失其作用域的问题 。 我在一个数组中有以下两个对象(简化以显示问题)Javascript 回调函数缺少所需数据的作用域,javascript,node.js,sockets,websocket,Javascript,Node.js,Sockets,Websocket,我遇到了回调函数的变量丢失其作用域的问题 。 我在一个数组中有以下两个对象(简化以显示问题) const search=[{socket:newwebsocket('ws://live.trade/123')}, {socket:newWebSocket('ws://live.trade/xyz')}); 然后,我对它们执行forEach,试图在套接字打开后记录套接字url search.forEach(函数(元素){ on('open',function open(){ log(elemen
const search=[{socket:newwebsocket('ws://live.trade/123')},
{socket:newWebSocket('ws://live.trade/xyz')});
然后,我对它们执行forEach,试图在套接字打开后记录套接字url
search.forEach(函数(元素){
on('open',function open(){
log(element.socket.url);
});
});
我觉得原因是,当函数open()运行时,元素不在作用域中,它只使用上一个元素(即ws://live.trade/xyz)。
这是正确的吗?最后,解决这个问题的方法是什么?它的真正用途是当套接字打开时,我需要通过调用它的套接字将版本数据发送到服务器。。。现实中我会有很多套接字,我不想为每个套接字写一个“socket.on('open'…)”
有什么建议吗
非常感谢 回调(即在socket.on()中)使用forEach()的元素变量。从您的实际结果来看,这可能意味着:
1.范围问题
由于javascript/节点作用域机制,变量可能在迭代过程中被“重写”,您给出的代码并非如此,但在循环中使用作用域是一个常见问题
在这种情况下,您必须执行以下操作:
search.forEach(function(element){
element.socket.on('open', function(){
console.log(this.socket.url);
}.bind(element));
});
说明:
bind()
将其第一个参数(本例中的元素变量)作为其内部的this
传递给匿名函数
- 在回调函数中,
this.socket
在适当的迭代中相当于element.socket
[UPDATE]在指出之后,forEach()为每个元素提供了一个作用域
有关更多详细信息,请参阅
2.依赖性问题
如果这不是范围问题,则可能意味着您正在使用的库无法按预期工作。也许,尝试在forEach()中记录元素
,以检查WebSocket对象是否符合您的预期
编辑
- 有关node/js循环和参考的更多信息,请参阅
- 对于一般的节点/js闭包:请参见
您是正确的,element.socket.url
将显示其最后一个值。我想你需要使用这个
关键字。不太熟悉套接字,但类似于this.url
的东西可能是“这正确吗?”不。JavaScript有词法范围。你在用哪个图书馆?我假设您使用的是一个,因为本机WebSocket
实例没有on
方法。我使用的是“ws:a NodeJS WebSocket library”“由于javascript/节点作用域机制,此变量在迭代过程中被覆盖。”这是不正确的。每个函数调用都有自己的作用域。证据:。你是对的!我将编辑我的答案,使其不那么“必要”。根据我的经验,我没有尝试就回答了这个问题,在这种情况下需要改进。。我是stackoverflow新手,我必须删除或编辑我的答案吗?将元素对象绑定到内部函数完成了这个技巧!为了更好地理解绑定函数,我将对其进行更多的阅读!非常感谢苏的帮助,也感谢@FelixKling@BrentAureli:虽然它可以工作,但您问题中的代码不可能有此问题,除非WebSocket
已损坏(但GH上的代码看起来很好)或者您正在以某种方式更改数组中的对象。让我们试试更简单的。如果这样做会怎么样:search.forEach(函数(元素){var socket=element.socket;socket.on('open',函数open(){console.log(socket.url);});})代码>编辑答案以删除不正确的语句将是一个开始。您仍然可以保留您的解决方案作为可能的解决方法。
search.forEach(function(element){
element.socket.on('open', function(){
console.log(this.socket.url);
}.bind(element));
});