Callback function missing scope for required data - javascript

I have a issue with a callback function's variable losing its scope
.
I have the following 2 objects in an array(simplified down to show the problem)
const search = [{socket: new WebSocket('ws://live.trade/123')},
{socket: new WebSocket('ws://live.trade/xyz')}];
I then do a forEach on them in an attempt to log the sockets url once the socket is open.
search.forEach(function(element){
element.socket.on('open', function open() {
console.log(element.socket.url);
});
});
*actual output*
ws://live.trade/xyz
ws://live.trade/xyz
*expected*
ws://live.trade/123
ws://live.trade/xyz
I feel like the reason is that when the function open() runs element is not in scope and it just uses whatever was last there(being the ws://live.trade/xyz).
Is this correct? And finally what would be the way to go about fixing this? The real use for this is when the socket is opened I need to send version data to the server via the socket that called it... Im going to have many sockets in reality and dont want to write a "socket.on('open'...)" for each individual one.
Any suggestions?
Thanks so much!

Your callback (i.e. in socket.on()) uses the element variable of the forEach(). From your actual result, it could mean that:
1. Scope issue
The variable could be "overriden" over the iterations because of javascript/node scope mechanism, it is not the case with the code you gave but it is a common issue working with scopes inside loops.
in this case you would have to do :
search.forEach(function(element){
element.socket.on('open', function(){
console.log(this.socket.url);
}.bind(element));
});
Explanation:
bind() passes its first argument (the element variable in this case) to the anonymous function as this inside it.
Inside your callback function, this.socket is equivalent to element.socket at the appropriate iteration
[UPDATE] after pointed out by Felix Kling, forEach() provides a scope for each element.
See bind for more details.
2. Dependency issue
If it is not a scope issue, it could mean that the library you are using does not work as expected. Maybe, try to log element inside the forEach() to check if the WebSocket objects are what you expect.
edit
For further reading on node/js loops and reference: see here
For node/js closures in general: see here

Related

strange way of passing arguments in express.js source code

When I was looking for source code of express router i saw this:
var debug = require('debug')('express:router:route');
can someone explain what this way of passing arguments mean?
In Javascript, functions are "first class", meaning they can be passed around like any other values.
require('debug') returns a function. As in, the default export of the debug npm package is a function, not an object.
That function is then called with the string "express:router:route"
A function that takes in some state or config, and returns a function based off that state or config, is partial application. This isn't a case of partial application, though, it's just a shorthand for:
var debug = require('debug');
debug('express:router:route');
require isn't a function that's meant to be partially applied, it just means that the debug package is returning a function, and it's being executed in place.
This is a technique as a part of functional programming, called currying, where the function has two arguments, and you can pass the first one and the second one separately.
It is a little hard to get your head around, but worth studying
What is Currying?
Currying is a process in functional programming in
which we can transform a function with multiple arguments into a
sequence of nesting functions. It returns a new function that expects
the next argument inline. It keeps returning a new function (that
expects the current argument, like we said earlier) until all the
arguments are exhausted. The arguments are kept "alive"(via closure)
and all are used in execution when the final function in the currying
chain is returned and executed.
More info here: https://blog.bitsrc.io/understanding-currying-in-javascript-ceb2188c339
Take a look at the debug package (link):
debug exposes a function; simply pass this function the name of your module, and it will return a decorated version of console.error for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
So, require('debug') returns a function. That function can be called by doing require('debug')(some parameter). Which means the following is possible (example taken from the debug docs linked above):
var debug = require('debug')('http')
Now the variable debug points to the result of calling the function returned require('debug'), with the parameter 'http'.

What is the difference between (function(){/*.....*/})(); and (function($){/*.....*/})(jQuery);

Is there difference between :
(function() {
/*..........*/
})();
and :
(function($) {
/*..........*/
})(jQuery);
Other people explained what the difference is, but not why you use the latter.
The $ variable is most often used by jQuery. If you have one script tag that loads jQuery and another that loads your code, it's perfectly fine. Now throw prototype.js into the mix. If you load prototype.js and then jQuery, $ will still be jQuery. Do it the other way around and now $ is prototype.js.
If you tried to use $ on such a page, you'd likely get errors or weird behavior.
There are many questions on StackOverflow about this problem. Plugins shouldn't assume much about the page they're loaded in, so they use this pattern defensively.
i am asking if there is difference between (function(){/…/})(); and (function($){/…/})(jQuery);
A little difference. In case of (function($){/*…*/})(jQuery); and absense of jQuery you'll get an error message immeditally after page loads. It's a simpler to detect jquery absense or incorrect order of scripts inclusion, when jquery-based code included before jQuery.
In case of (function(){/*…*/})(); you'll get an error message when code inside this construction actually call one of jQuery methods. It's harder to detect this error, but on the other side you can include your jquery-based scripts before jquery.
I prefer first case.
The second form, (function($){/*…*/})(jQuery); can be slightly safer when working in an environment where you don't (or can't) strictly enforce what code gets put on your site.
I used to work on a large site with a lot of third-party ads. These ads would often unsafely inject their own version of jQuery and occasionally they would override jQuery's global $ object. So, depending on how we wrote our code, we might be calling methods that no longer existed or had slightly different behaviour from what we expected. This could be impossible to debug, since some ads would never appear in our area or were excluded from our environment. This meant we had to be extremely protective of scope, inject our dependencies before any ad code had a chance to load, namespace anything that had to be global and pray no ad screwed with us.
Other answers are quite fragmented so I'd like to give a more detailed answer for the question.
The main question can be self-answered if you understand..
What does (function(argument){ /*...*/ })(value); mean?
It's a quick hand version of:
var tempFunction = function(argument){
/* ... */
}
tempFunction(value);
Without having to go through the hassle of conjuring up a new terrible name for a function that you will only call once and forget. Such functions are called anonymous functions since they aren't given a name.
So (function(){/*...*/})() is creating a function that accept no argument and execute it immediately, while (function($){/*...*/})(jQuery) is creating a function that accept one argument named $, and give it the value of jQuery.
Now that we know what the expression means, surely the first think on our mind is
"Why?". Isn't $ jQuery already?
Well, not exactly. We can never be sure. $ is an alias of jQuery, but other libraries can also use the same alias. As user #FakeRainBrigand already pointed out in his answer, prototype.js also use $ as its alias. In such cases, whichever library assigns its value to $ later wins out.
The practice of (function($){...})(jQuery) is very similar to an alias import in other programing languages. You are explicitly telling the system that your function:
Requires an object/library named jQuery, and
Within your function, $ means jQuery.
So even when someone include a new library later that override the alias $ at the global level, your plugin/framework still works as intended.
Because javascript is so... "flexible" in variable assignment, some people (including me) go as far as doing things like
var myApplication = (function($, undefined){ ... })(jQuery);
Apply the same understanding, it is easy to interpret the second argument part as: assign nothing to the variable undefined. So we can be sure that even if some idiot assigned a value to undefined later, our if(checkVariable === undefined){} won't break. (it's not a myth, people really do assign values to undefined)
When is it commonly used in javascript?
This anonymous function practice is most commonly found in the process of providing encapsulation for your plugin/library.
For example:
var jQuery = (function(){
var publicFunction = function(){ /* ... */}
var privateFunction = function(){ /* ... */}
return {
publicFunction : publicFunction
}
})();
With this, only jQuery.publicFunction() is exposed at the global scope, and privateFunction() remains private.
But of course, it is also used any time you simply want to create a function, call it immediately, and throw it away. (For example as a callback for an asynchronous function)
For the bonus question
why they used (function(){}() twice in the below code?
Well, most likely because they don't know what they're doing. I can't think of any reason to put nested function in like that. None at all.
(function(){/*...*/})(); does not set $ as reference to jQuery within IIFE and (function($){/*...*/})(jQuery); sets $ or other parameter name; e.g.; (function(Z){/*...* Z("body") where Z : jQuery*/})(jQuery); as reference to jQuery within IIFE
The they are both closures. The first is just an anonymous function that will fire any well formatted code that is inside immediately. The second is the jQuery closure. It is how the jQuery library initiates it wraps its code in the JQuery object and exposes it isn't the $ symbol.
(function(){}()) // this is a closure
(function($){}(jQuery)) // is a closure that wraps the executed code inside of the jQuery returned object and exposes it via the $.
With this (function(){/*…*/})();, you are not passing any argument to the inner function, while with this (function($){/*…*/})(jQuery); you are passing jQuery as argument to the inner function and expecting its value as $(which means, you will be able to use jQuery inside the inner function).
Ex:
(function($){
$(document).ready(function() {
console.log('all resources loaded');
})
})(jQuery);
They both are examples of Immediately Invoked Function Expression. In that sense, there is no difference between (function(){/*…*/})(); and (function($){/*…*/})(jQuery);. So no benefits are gained by wrapping (function($){/*…*/})(jQuery); inside (function(){/*…*/})();
A new execution context is created when a function is executed. So when (function(){/*…*/})(); is executed a context is created. Again when (function($){/*…*/})(jQuery); is executed, another context is created. Since the first context is not used (i.e. no variables are declared inside it), I don't see any advantages gained by the wrapping.
(function() { // <-- execution context which is not used
(function($) { // <-- another execution context
"use strict";
/*..........*/
})(jQuery);
})();

Function assignment doesn't work

I'm new to Node.js. I have searched the forum but couldn't find a similar question. Here is the problem I encountered. The following code runs fine.
process.stdout.write("hello world!\n");
but the following code:
var myprint = process.stdout.write;
myprint("hello world");
will generate the following error:
TypeError: Cannot read property 'defaultEncoding' of undefined
Any suggestions? Thank you so much.
Probably, the write() method needs to be called with the correct object reference so the write() method knows what stream it is writing to. There are multiple ways to work around this. Here's one way:
var myprint = process.stdout.write.bind(process.stdout);
myprint("hello world");
See .bind() on MDN for more info.
For future reference, when you do:
var myprint = process.stdout.write;
myprint only contains a reference to the write method and that method is then called with no object reference. That means that the this pointer inside the write() method will not point at the stdout stream like it would when you call it as process.stdout.write(). If a method needs it's instance data (which most methods do), then this creates a problem. You can "bind" the object reference to a new temporary function using .bind() which allows you to assign it to another variable and then use it directly like you were attempting to do.
The write function is trying to access a variable on the this variable, which is not set to process.stdout when you call myprint, unlike when you call process.stdout.write.
Note that
var out = process.stdout;
out.print('wow\n');
will work as expected.

Understanding jquery source code

I have recently started to delve deeper in to JavaScript and have come across this code construct in JQuery.
(function( window, undefined ) {
})(window)
Reading on stack overflow (and elsewhere) I have come to the conclusion that this is the same as
function foo(window, undefined) {
...
}
foo(window);
Am I correct in my assumption?
If so, what are the advantages of the former? (other than confusing newbs)
There are several things you need to know to make sense of it:
It is an anonymous function, which simply means it does not have a name.
The function is called immediately after it is declared. You see the open parenthesis on line 2, immediately after the function definition? That means, "call this function".
Only one parameter is passed to the function. That parameter is "window", which is the name of the global scope inside of a browser.
The function being called actually expects *2* parameters, but we're calling it with one. Javascript lets you call functions with more or fewer parameters than the function actually expects. There are ways of getting to the list of parameters that was passed.
Since we are only passing one parameter, the second parameter will automatically be set to "undefined". "undefined" is a special javascript value that means, get ready, "undefined".
It just so happens that we have also named our second parameter with the name "undefined". So in effect, we have created a local variable (parameters are very much like local variables) that is named undefined, and whose value is undefined.
Why on Earth did we do that? It is a way of ensuring that, within our anonymous function, if we refer to "undefined", it really will have the value of "undefined". If we didn't do that, and some crazy code outside of our scope redefined "undefined" (by saying something like "undefined = 42"), then we'd write code thinking we were referring to undefined but we'd actually be referring to 42. These shenanigans with passing 1 parameter but expecting 2, and calling the second one undefined, protects us from such nonsense.
I hope that's clear, let me know if it is not. I learned all that from Paul Irish's video mentioned above.
This is an anonymous function. It is created and then goes out of scope, which here is the advantage. It is created and instantiated immediately. What is good about this is that it is not going to collide with any function on the global namespace, and thus will not obliterate anything you may have included on the page.
It is an anonymous function, it has quite a few benefits, like being only active in the current scope. You can read more about it here.

common reasons for javascript reference error with prototype

I am new to the prototype framework and fairly new to Javascript (it's been a long while sicne any heavy javascript work). I have defined a class that is calling another method within it and I keep getting a ReferenceError "getLabel is not defined". getLabel is another class method that I am trying to call. Here is the code where I am calling it:
var title = new Element('td');
title.addClassName(label_class);
title.addClassName('scorecard_tee_title');
title.appendChild(new Element('span').update(getLabel(tee, true)));
I have tried using this.getLabel as well but to no avail. I'm guessing that I have a syntax error in my class (which is too large to place here), but can't find what's wrong.
What should I be checking for? Are there any common reasons for this error to be thrown that I should keep in mind when using Prototype?
Thanks!
UPDATE: I pulled the getLabel function out of my class and it works fine, which leads me to believe that it is in some way related to the getLabel function being passed into or evaluated as a member of the class and not a standalone function. Still not sure what I'm doing wrong though.
It is my understanding (which I admit, is pretty limited when it comes to object oriented programming), that you don't call methods as functions directly. They need to be called as methods for an object. For instance:
getLabel(foo);
If getLabel is method of a class, it modifies an object. In your example, you are not modifying an object, so what is getLabel actually getting the label for? If it's getting the label of tee, then you'd want:
tee.getLabel();
But if I'm wrong, somebody let me know and I'll delete this.
You need to reference getLabel somehow, either classInstance.getLabel() or this.getLabel(). I see you already tried the later so I'm assuming this code is not running inside the same class as getLabel() belongs to?
The problem with the undefined methods was being caused because the method that was calling them were being called from anonymous function. Binding the anonymous function to (this) from where it was being created works.
I realized this when I looked at 'this' in Firebug and realized it was pointing to Window and not Object.

Categories

Resources