简体   繁体   English

socket.on内部未定义的套接字

[英]socket undefined inside of socket.on

I have the current code; 我有当前代码;

socket.on('KeyPress', function(data){
    var ply = PLAYER_LIST[socket.id];
    /* ... */
 });

WebStorm is informing me that socket.id may not be initialized, and then when this event is triggered it does cause the error WebStorm通知我未初始化socket.id,然后在触发此事件时确实导致了错误

TypeError: Cannot read property 'id' of undefined

The whole code is inside of 整个代码在内部

io.sockets.on('connection', function(socket){ /*...*/ });

Here is two of the on method I'm using; 这是我正在使用的两种on方法; 在此处输入图片说明 In the first block you can see I'm doing the same thing yet it works.. 在第一个块中,您可以看到我正在做同样的事情,但它仍然有效。

Also on that note how secure is it to use socket.id to auth a user? 还要注意,使用socket.id对用户进行身份验证有多安全? Is it possible to force-set your own id? 是否可以强制设置自己的ID?

You are a victim of a bad practice of defining variables with var within a loop and then getting bit by the influence of "variable hoisting" where a variable defined with var anywhere in the function is automatically declared at the start of the function and then initialized where your assignment was, meaning it's undefined everywhere in your function before that. 您是在循环中使用var定义变量,然后受“变量提升”的影响的错误做法的受害者,在变量“提升”中,在函数的任何位置使用var定义的变量都会在函数开始时自动声明,然后初始化您的分配在哪里,这意味着在此之前函数中的每个地方都undefined它。

The problem is this line of code: 问题是这行代码:

var socket = SOCKET_LIST[i];

That is redefining a local variable named socket that hides the one you actually want. 那就是重新定义一个名为socket的局部变量,该变量隐藏了您真正想要的变量。 Variables defined with var are function scoped. var定义的变量是函数范围的。 That means they are defined at the top of the function (this is called variable hoisting) and thus hides the other parent scoped socket variable. 这意味着它们在函数的顶部定义(这称为变量提升),从而隐藏了其他父级作用域socket变量。

Think of your function as starting like this: 将您的函数想像成这样:

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
});

This is essentially how Javascript sees your code. 本质上,这就是Javascript看到您的代码的方式。 You can do a search on "Javascript variable hoisting" and see LOTS of articles written on the topic if you want more info. 您可以在“ Javascript变量提升”上进行搜索,如果需要更多信息,可以查看有关该主题的文章的全部内容。

The smallest change you can make it to change the name of this local variable to something else to it doesn't interfere with the parent scoped variable, but really this code structure is not ideal in the first place. 您可以进行的最小更改,以将该局部变量的名称更改为其他名称,从而不会干扰父范围变量,但是实际上,此代码结构首先并不理想。

var localSocket = SOCKET_LIST[i];
var ply = PLAYER_LIST[p];
localSocket.emit(...)

In general it's a bad practice to define a variable with var inside a for loop. 通常,在for循环内使用var定义变量是一种不好的做法。 It leads to the "assumption" that it is scoped only to that loop, but in reality, it's scoped to the whole function and can mess with things outside of the loop. 它导致“假设”,它仅适用于该循环,但实际上,它适用于整个功能,并且可能使回路外的内容混乱。

In ES6, you can use let or const instead of var to declare a variable that is actually scoped to only the block of the loop. 在ES6中,可以使用letconst代替var来声明一个变量,该变量实际上仅作用于循环块。

Of other note, you should NEVER be iterating arrays with for/in . 另外要注意的是,永远不要使用for/in迭代数组。 That iterates all array properties (including other enumerable object properties), not just array elements. 这将迭代所有数组属性(包括其他可枚举的对象属性),而不仅仅是数组元素。 ES6 adds for/of for iterating arrays this way. ES6通过这种方式添加了for/of来迭代数组。 In ES5, you can use the more traditional for loop or .forEach() . 在ES5中,可以使用更传统的for循环或.forEach()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM