Is there a more readable way to express javascript closures? - javascript

I would like to update some data with JSON when the user clicks on an object. What I came up with is the following double closure.
var buildGetJSON = function(m,t,p,u) {
return function () {
var buildUpdateParticipants = function(m,t,p) {
return function(data) { updateParticipants(m,t,data,p); };
};
$.getJSON(u, buildUpdateParticipants(m,t,p));
};
};
marker.on("click", buildGetJSON(marker, title, popmsg, url));
It works, but made me wonder if there is a more concise way to put this than writing a closure variable for the two function calls. Any hints?

Yes, the second closure is redundant.
function buildGetJSON(m,t,p,u) {
return function() {
$.getJSON(u, function(data) {
updateParticipants(m,t,data,p);
});
};
}
marker.on("click", buildGetJSON(marker,title,popmsg,url));
If you're only using buildGetJSON once, you can further simplify it by making buildGetJSON anonymous.
marker.on("click", function(m,t,p,u) {return function() {
$.getJSON(u, function(data) {
updateParticipants(m,t,data,p);
});
};}(marker,title,popmsg,url));
Here's another way to do it entirely with anonymous functions. It doesn't collapse into as few lines, but I think it looks a little clearer.
!function(m,t,p,u) {
marker.on("click", function() {
$.getJSON(u, function(data) {
updateParticipants(m,t,data,p);
});
});
}(marker,title,popmsg,url);

Why not simply do this?
marker.on("click", function () {
$.getJSON(url, function (data) {
updateParticipants(marker, title, data, popmsg);
});
});
Looks much more synoptical - at least to me :-)
But be aware: if the variables marker, title etc. can change, and you don't want that, then you need an additional closure. E.g. if you call this for example in loop, and the variable marker (or other variables) changes over the loop! Then you need to enclose your code in another closure within the loop:
for (marker in markers) {
(function (marker) {
// above code
})(marker);
}
Closures are very nice and very strong feature of JavaScript, once you know how to use them. Look at the "The JavaScript Programming Language" videos from Douglas Crockford, they explain it in a great way.

Related

Calling a nested function present inside JQuery declaration

I have a function called "destination" nested in scrip1.js file. If I add this file at the end of webpage using , how can I trigger it at the next step? Here are some contents of script1.js.
script1.js
$.something = function(element, options) {
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
}
$("body").on("click", ".notify-btn", function (event) {
event.preventDefault();
destination(some args);
});
someOtherFunction();
start();
}
$.fn.something = function (options) {
return this.each(function () {
if (undefined == $(this).data("something")) {
var plugin = new $.something(this, options);
$(this).data("something", plugin);
}
});
};
I tried this, but is not working. Chrome console is showing error about this function.
<script type="text/javascript" src="script1.js"></script>
<script>
$.fn.something().destination();
</script>
I can not change this script1.js, so any possible way?
There's no specific connection between variables declared during function execution - and how the rest of the world sees the result of execution. So this code:
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
}
start();
... lets destination value (remember, functions in JS are first-class citizens) go away when start() completes its execution. That's actually quite convenient if you want to encapsulate some implementation details and hide it from users; this technique (also known as Module pattern) was often used in pre-class world to implement private properties in vanilla JavaScript.
However, all the values returned from a function can be reused. For example, here...
$.something = function(element, options) {
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
return {
destination
};
}
return start();
}
... you make destination function a part of object that is returned from start(). Now $.something returns an object, too; that means it can be reused:
var plugin = new $.something(this, options);
// ...
plugin.destination('some', 'args');
If you're afraid changing the return value might hurt someone, you can try to assign value of destination to $.something object itself as its property, like this:
$.something = function(element, options) {
function start() {
function destination(arg1, arg2..) {
$.notify(some args);
}
return destination;
}
// ...
const destination = start();
$.something.destination = destination;
}
The returned value is not modified, yet function is accessible. Still, that's not actually a good workaround; the biggest issue is that any subsequent calls on $.something will rewrite the value of that function, which might be not a good thing if its execution depends on some scoped variables.
While technically there's a way to fetch destination function code by parsing $.something source code, I really doubt it's worth the effort in your case.

Call back when using pre-defined function

I've declared a new function. Then I'm calling that function later. How do I run code only if the function I'm calling has completed.
this is my code
var callLogin = function() {
$(document).ready(function() {
if(document.getElementById("userLoggedIn") === null) {
$(".cover").fadeIn(200);
$(".sixPinInputContainer").fadeIn(200);
$("#pageBody").css("overflow", "hidden");
$('.sixPinInput').first().focus();
};
})
};
Then This is where I call It. The problem is that it's running the .load before it calls my pin container so even if pin is incorrect it runs code.
if (startBtn) {
callLogin()
$("#" + rowID).load("eventHandlersPHP/updateStart.php", {
roomID: id }, function(data, status) {
$("#notStartedCount").load("eventHandlersPHP/jobsNotStartedCount.php");
})
};
This is documented pretty well here. You could create some sort of action that'll trigger the one function, then it can call the other. Also, this will probably be a more helpful place for what it is you're trying to do.
-Gonzo

Why can't I use this in (JavaScript) Worker when defining an object?

Coming from the Java (OOP) world, I am used to classes, inheritance and multi threading. Now for my little walkabout in the JavaScript domain, I try to utilize these paradigms and patterns where applicable. Read: use prototypes ("classes" / objects) and WebWorkers for parallel execution. However, this one case does not work ...
HTML site starting a worker:
<html>
<head>
<script>
var worker = new Worker("worker.js");
worker.onmessage(event) {
// here be fancy script
}
worker.postMessage("run, worker, run!");
</script>
</head>
...
</html>
Worker called by HTML ("worker.js"):
self.loadScripts("handler.js");
var handler = null;
self.onmessage = function(event) {
if(!handler) {
handler = new Handler();
}
handler.compute();
}
The Handler as called by the worker ("handler.js"):
function Handler() {
}
Handler.prototype = {
compute: function() {
this.doSomething(); // <-- ERROR! "this" points to the worker context,
// not to the Handler instance. So "doSomething" is
// undefined. However, the following line would work:
// Handler.prototype.doSomething();
},
doSomething: function() {
// More code here
}
}
Is JavaScript prototyping and "inheritance" meant to work this way? Should I always use the prototype property instead of this? What if I want to access this.myProperty instead of a function?
Also: is there any reasonable way to bind this to the Handler instance in the constructor? At least the code is not cluttered with lengthy Handler.prototype references.
Thanks!
Thank you for your comments. Indeed, the context of this works as expected. The real code used a timeout callback:
Handler.prototype = {
compute: function() {
self.setTimeout(this.doSomething, 1000); // Here the this got lost
},
doSomething: function() {
// Code here
}
}
It seems this from a timeout call is referencing the worker context. To solve the issue, I just wrapped the callback in an anonymous function (referencing the caller as a variable, as jfriend00 suggested):
Handler.prototype = {
compute: function() {
var caller = this;
self.setTimeout(function() { // Wrap for great justice
caller.doSomething();
} , 1000);
}, doSomething: function() {
// Code here
}
}
Thanks again.

Better way for writing JavaScript function

The following ways of writing a javascript function are equivalent.
Maybe the first one is more clear.
Nevertheless, many programmers prefer the second way.
There are significant difference between the two ways for preferring the second-one?
First way:
Class.prototype.fn = function () {
var obj = {
…
};
return obj;
};
Second way:
Class.prototype.fn = function () {
return {
.........
};
};
Unless you need to perform an operation on obj after creating it via the literal, there's no difference and it's just a subjective style preference. (Note that said use could be in the code, or during debugging; more below.)
So for example, there's a real practical difference here:
Class.prototype.fn = function () {
var obj = {
subordinate: {
foo: function() {
if (obj.flag) {
doOneThing();
}
else {
doSomethingElse();
}
}
}
};
return obj;
};
There, you need the name, so that obj.subordinate.foo() works. (Not that I'd advocate doing this, but it's an example of when there's an objective rather than subjective distinction.) But barring needing to use it after initialization and before return, it's just a subjective thing.
Of course, that use need not necessarily be in the code. The form with the obj variable can be more useful when debugging, if you need to inspect what you're returning before you return it.
Perhaps going a bit off-piste here, but I think it's related: In contrast to the examples in your question, there's a real, practical, tangible difference between this:
Class.prototype.foo = function () {
…
};
Class.prototype.bar = function () {
…
};
and this:
(function() {
function Class_foo() {
…
}
function Class_bar() {
…
}
Class.prototype.foo = Class_foo;
Class.prototype.bar = Class_bar;
})();
...that difference being that in the former, the functions have no names (the properties referring to them do, but not the functions themselves). In the latter case, the functions have real names, which help your tools help you by showing you names in call stacks, lists of breakpoints, etc.

Javascript code as a variable

Ok, this may sound a bit crazy but hear me out :)
I would like to do the following in javascript:
define START_OF_EVERY_FUNCTION = "try {"
define END_OF_EVERY_FUNCTION = "} catch () {}"
function TEST () {
START_OF_EVERY_FUNCTION
// rest of function
END_OF_EVERY_FUNCTION
}
Basically, can I define a list of javascript lines (code) and include them as above? I'm looking for a technique versus comments about whether this is a good idea or not or debate over wrapping all functions in a try/catch block.
I know about eval(), but I dont think you can eval statements like the above.
This might be goofy but you could define a master function and run other functions through it by passing them in.
var execute = function(func){
alert('before');
func();
alert('after');
};
function sayHi(){
alert('hi there');
}
execute(sayHi);
As requested, an example with passing arguments.
var execute = function(func){
alert('before');
var ret = func.apply(null, Array.prototype.slice.call(arguments, 1));
alert('after');
};
function saySomething(sayWhat){
alert(sayWhat);
}
execute(saySomething,'hey there');
That is not allowed in JavaScript.
You could extend the Function prototype:
Function.prototype.tryThis = function() {
try {
this();
}catch(ex){
alert('Caught '+ex);
};
};
function tryIt() {
alert('Inside tryIt');throw "My Error from tryIt";
}
tryIt.tryThis();
You need to look into aspect oriented programming for JavaScript. You can create hooks for function entry and exit. Tools like JSUnit do this for example.
I think you can do this with the "new Function" operator. I've never used it myself, since I'm not clinically insane, but I believe you can pass it a string which it will evaluate and use as the function body. You can also get the code for each function by calling myFunction.toString(). So put together, it'd be something like this:
var functionsToMessUp = ['myFunc1', 'myFunc2'];
for (var i = 0; i < functionsToMessUp.length; ++i) {
var theFunc = window[functionsToMessUp[i]]; // assuming they're in global scope
window[functionsToMessUp[i]] = new Function(
START_OF_EVERY_FUNCTION
+ theFunc.toString()
+ END_OF_EVERY_FUNCTION
);
}
Now, the above almost certainly won't work - there's parameters and other things to take into consideration, and I don't even think that's how the new Function constructor works, but if you really want to go down this path (which I really don't recommend), then this might be a good starting point for you.
Maybe something like this?
function tryCatch(callback) {
try {
callback();
} catch() {}
}
var myFunction = function() {
// do some stuff
};
tryCatch(myFunction);

Categories