7
\$\begingroup\$

I've finally gotten around to learning Lisp/functional programming. However, what I've noticed is that I'm trying to bring ideas back into JavaScript.

Example

Before

var myPlacemark,
    myLineString;

myLineString = ge.createLineString('');
myLineString.setLatitude(100);
myLineString.setLongitude(-100);
myPlacemark = ge.createPlacemark('');
myPlacemark.setGeometry(placemark);

After

var myPlacemark;

myPlacemark = (function(point, placemark){
  point.setLatitude(100);
  point.setLongitude(-100);
  placemark.setGeometry(point);
  return placemark;
})(ge.createPoint(''), ge.createPlacemark(''));

Is there any reason I shoudn't be doing it the 2nd way?

\$\endgroup\$

3 Answers 3

13
\$\begingroup\$

What you have there is actually just a fancy assignment operation. The closure there plays no role. And if you would need to set another placemark, you would have to repeat the code or wrap in one more function.

IMHO, it would be much more pragmatic to use a lot simpler approach:

var createPlacemark = function (point, placemark) {
        point.setLatitude(100);
        point.setLongitude(-100);
        placemark.setGeometry(point);
        return placemark;
    },
    myPlacemark = createPlacemark(ge.createPoint(''), ge.createPlacemark(''));

This way you get reusable routine with a clear name. And if goal of this all was to prevent external sources from adding placemarks, just warp it all in the standard:

(function () {

}());

The bottom line is: you were over-thinking it.

\$\endgroup\$
5
  • \$\begingroup\$ I'm aware that it's not exactly helping my code readability. My question was more so regarding the performance penalties that might result from going 'closure crazy'. \$\endgroup\$
    – ilia choly
    Commented Sep 11, 2012 at 4:21
  • \$\begingroup\$ In your example there would be no performance penalty. The processing costs for closures are negligible. What you have to worry about sometimes is the memory leaks. You can end up binding variables with large amount of data (common mistake in dealing with XHR), which is never garbage-collected. But that does not seem possible in your situation. \$\endgroup\$
    – tereško
    Commented Sep 11, 2012 at 4:38
  • \$\begingroup\$ I tend to agree with what you're saying @teresko, except for 1 thing: if the OP doesn't wrap the lot in a function, there is one more global being created in the first version, and that's one too many IMO \$\endgroup\$ Commented Sep 11, 2012 at 20:50
  • \$\begingroup\$ If you are referring to createPlacemark, then it is just a different way of defining function. But if you are talking about myPlacemark not having var in front of it, then you missed the comma in previous line. Basically, I do not get what you meant with the "one more global". \$\endgroup\$
    – tereško
    Commented Sep 11, 2012 at 21:12
  • \$\begingroup\$ @tereško The scope of myLineString is global. The scope of point is the function. So in the second example the global variable myLineString doesn't exist. \$\endgroup\$ Commented Sep 12, 2012 at 3:06
4
\$\begingroup\$

While using a closure to prevent polluting the global namespace is a good idea, you shouldn't be passing in random data like that. The way you are doing it, you are forcing the reader to scroll to the bottom of the function call before reading the function body - that's just plain confusing for no good reason.

Instead, declare the variables regularly within the closure, and assign their values right then and there. That way, it's much easier to read (and maintain), while still keeping the global namespace intact.


In addition, Crockford suggests that you put the calling parentheses inside the wrapping parenthesis.


With all that in mind, here's your code, refactored:

var myPlacemark = (function() {

  var point = ge.createPoint(''),
      placemark = ge.createPlacemark('');

  point.setLatitude(100);
  point.setLongitude(-100);

  placemark.setGeometry(point);

  return placemark;

}());
\$\endgroup\$
1
  • \$\begingroup\$ Plus this would finally become a real closure, not just a function object, since it closes over the ge from the outer scope. Strangely enough, this namespace pollution prevention is easier in java using simple nested block {}, since it creates a sub-scope – in javascript it doesn't. \$\endgroup\$
    – charlie
    Commented Sep 21, 2012 at 9:55
2
\$\begingroup\$

It would be a real closure only if you had done one of the following:

function createPlacemark(placemark, point, latitude, longitude) {
    point.setLatitude(latitude);
    point.setLongitude(longitude);
    placemark.setGeometry(point);
    return placemark;
}

function closure1(point, placemark) {
    return function(latitude, longitude) {
        return createPlacemark(placemark, point, latitude, longitude);
    };
}

function closure2(latitude, longitude) {
    return function(point, placemark) {
        return createPlacemark(placemark, point, latitude, longitude);
    };
}

var myPlacemark1 = closure1(ge.createPoint(''), ge.createPlacemark(''))(100, 100);
var myPlacemark2 = closure2(100, 100)(ge.createPoint(''), ge.createPlacemark(''));

i.e. capture context variables in a closure. A function object is not necessarily a closure.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.