我有当前代码;
socket.on('KeyPress', function(data){
var ply = PLAYER_LIST[socket.id];
/* ... */
});
WebStorm 通知我 socket.id 可能未初始化,然后当触发此事件时,它确实会导致错误
TypeError: Cannot read property 'id' of undefined
整个代码都在
里面io.sockets.on('connection', function(socket){ /*...*/ });
这是我正在使用的两个 on 方法; 在第一个 block 中,您可以看到我正在做同样的事情,但它有效..
另外,使用 socket.id 来验证用户的安全性如何?是否可以强制设置自己的id?
最佳答案
您是在循环中使用 var
定义变量的不良做法的受害者,然后受到“变量提升”的影响,其中使用 var
定义变量> 函数中的任何位置都会在函数的开头自动声明,然后在您的赋值所在的位置进行初始化,这意味着在此之前它在函数中的所有位置都是 undefined
。
问题出在这行代码:
var socket = SOCKET_LIST[i];
这就是重新定义一个名为 socket
的局部变量,它隐藏了您真正想要的变量。用 var
定义的变量是函数作用域的。这意味着它们是在函数的顶部定义的(这称为变量提升),从而隐藏了另一个父作用域的 socket
变量。
将您的函数视为这样开始:
socket.on('KeyPress', function(data) {
var socket; // this is hoisted from deeper inside the function
// and creates a new undefined socket variable
var ply = PLAYER_LIST[socket.id];
// other code here
});
这本质上就是 Javascript 如何看待你的代码。如果您想了解更多信息,可以搜索“Javascript 变量提升”并查看大量有关该主题的文章。
您可以将此局部变量的名称更改为其他名称的最小更改不会干扰父作用域变量,但实际上此代码结构一开始并不理想。
var localSocket = SOCKET_LIST[i];
var ply = PLAYER_LIST[p];
localSocket.emit(...)
<小时/>
一般来说,在 for
循环内使用 var
定义变量是一种不好的做法。它导致“假设”它的作用域仅限于该循环,但实际上,它的作用域是整个函数,并且可能会扰乱循环之外的事物。
在 ES6 中,您可以使用 let
或 const
而不是 var
来声明一个变量,该变量的作用域实际上仅限于循环。
值得注意的是,您永远不应该使用 for/in
迭代数组。它会迭代所有数组属性(包括其他可枚举对象属性),而不仅仅是数组元素。 ES6 添加了 for/of 来以这种方式迭代数组。在 ES5 中,您可以使用更传统的 for
循环或 .forEach()
。
关于javascript - socket.on 内部未定义套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47320378/